mirror of https://github.com/tongzx/nt5src
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.
541 lines
11 KiB
541 lines
11 KiB
/*++
|
|
|
|
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<u; i++) {
|
|
c = buf[i];
|
|
buf[i] = ( (c << 4 ) & 0xf0 ) | ( (c >> 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<NumDwords; i++) {
|
|
RetValue += *(BaseAddr+i);
|
|
}
|
|
|
|
return (RetValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
SimulateError(
|
|
DWORD ErrorType
|
|
)
|
|
|
|
|
|
{
|
|
|
|
LPDWORD lpdwPtr;
|
|
DWORD dw1,
|
|
dw2;
|
|
|
|
|
|
switch (ErrorType) {
|
|
case EXCEPTION_ACCESS_VIOLATION:
|
|
lpdwPtr = NULL;
|
|
*lpdwPtr = 5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
|
dw1 = 5;
|
|
dw2 = dw1 - 1;
|
|
dw2 = dw1 / (dw1 + dw2 - 9);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|