Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

715 lines
21 KiB

/***************************************************************************
Name : SENDFR.C
Comment :
Functions: (see Prototypes just below)
Copyright (c) 1993 Microsoft Corp.
Revision Log
Date Name Description
-------- ----- ---------------------------------------------------------
***************************************************************************/
#include "prep.h"
#include "efaxcb.h"
#include "protocol.h"
///RSL
#include "glbproto.h"
#define faxTlog(m) DEBUGMSG(ZONE_SENDFR, m)
#define FILEID FILEID_SENDFR
VOID BCtoNSFCSIDIS(PThrdGlbl pTG, NPRFS npfs, NPBC npbc, NPLLPARAMS npll)
{
// Use bigger buf. Avoid truncating Id before stripping alphas
char szCSI[MAXTOTALIDLEN + 2];
//BG_CHK(npbc->bctype==SEND_CAPS);
//BG_CHK(npbc->wTotalSize >= sizeof(BC));
ZeroRFS(pTG, npfs);
// extract ID
// GetTextId(npbc, szCSI, MAXTOTALIDLEN+1);
if (pTG->LocalID) {
strcpy (szCSI, pTG->LocalID);
}
#ifdef OEMNSF
CreateOEMFrames(pTG, ifrNSF, OEMNSF_POSBEFORE, npbc, npll, npfs);
#endif
// RSL no NSF
#if 0
// Send MS NSFs IFF ECM is enabled
if (1) /// RSL (pTG->ProtInst.llSendCaps.fECM)
{
// Now create MS NSx
CreateNSForNSCorNSS(pTG, ifrNSF, npfs, npbc, FALSE); // NO id in NSF
}
else
{
// zap MMR out of our DIS
npbc->Fax.Encoding &= (~MMR_DATA);
}
#endif
#ifdef OEMNSF
CreateOEMFrames(pTG, ifrNSF, OEMNSF_POSAFTER, npbc, npll, npfs);
#endif
if(_fstrlen(szCSI))
CreateIDFrame(pTG, ifrCSI, npfs, szCSI, FALSE); // RSL: DON'T strip non-numerics for CSI
CreateDISorDTC(pTG, ifrDIS, npfs, &npbc->Fax, npll);
}
VOID BCtoNSCCIGDTC(PThrdGlbl pTG, NPRFS npfs, NPBC npbc, NPLLPARAMS npll)
{
// Use bigger buf. Avoid truncating Id before stripping alphas
char szCIG[MAXTOTALIDLEN + 2];
BOOL fSkipDTC;
BOOL fSkipCIG;
BG_CHK(npbc->bctype==SEND_POLLREQ);
BG_CHK(npbc->wTotalSize >= sizeof(BC));
ZeroRFS(pTG, npfs);
fSkipDTC = 0;
fSkipCIG = 0;
// extract ID
GetTextId(npbc, szCIG, MAXTOTALIDLEN+1);
#ifdef OEMNSF
if(fUsingOEMProt)
{
WORD wFlags;
BG_CHK(wOEMFlags);
wFlags = CreateOEMFrames(pTG, ifrNSC, OEMNSF_POSBEFORE, npbc, npll, npfs);
fSkipDTC = ((wFlags & OEMNSF_DONTSEND_DCS) != 0);
fSkipCIG = ((wFlags & OEMNSF_DONTSEND_TSI) != 0);
}
else
#endif
{
if(npbc->wNumPollReq)
{
// if we have NSC poll reqs send NSC _with_ our ID. This is reqd
// for return addressing of response. See bug#6224 and 6675. In
// this case CIG is redundant so dont send it.
// NOTE: The real check we want to do is to see if we are polling
// another AtWork amchine or a G3. This test is just a proxy. The
// result is a residual bug that G3/blind-polls from IFAX-to-IFAX
// will NOT be routed correctly, even though they could/should.
// G3/Blind-polls from IFAX-to-G3 will never be routed correctly
// so long as we rely on the pollee to do the routing, but IFAX
// to G3 blind polls wil work if we replace the
// if(wNumPollReq)
// test with a
// if(pollee is AtWork)
//
CreateNSForNSCorNSS(pTG, ifrNSC, npfs, npbc, TRUE); // ID in NSC with poll req
fSkipCIG = TRUE;
}
else
{
// no NSC poll reqs, so only send our basic NSC
// (ie. to advert capabilities) if we have ECM
// Dont send our ID in this case. CIG is good enough
if(pTG->ProtInst.llSendCaps.fECM)
CreateNSForNSCorNSS(pTG, ifrNSC, npfs, npbc, FALSE); // no id in NSC w/o poll req
}
}
if(!pTG->ProtInst.llSendCaps.fECM)
{
// zap MMR out of our DTC
npbc->Fax.Encoding &= (~MMR_DATA);
}
if(!fSkipCIG && _fstrlen(szCIG))
CreateIDFrame(pTG, ifrCIG, npfs, szCIG, TRUE);
// Strip non-numerics for CIG. Our FULL ID (used for addressing the
// response) is sent in the NSC if we have NSC poll requests, so the
// CIG is only for G3 display purposes. Strip alphas to conform
// to spec & cut it down to size
if(!fSkipDTC)
CreateDISorDTC(pTG, ifrDTC, npfs, &npbc->Fax, npll);
}
void CreateNSForNSCorNSS(PThrdGlbl pTG, IFR ifr, NPRFS npfs, NPBC npbc, BOOL fSendID)
{
WORD wNumFrames;
USHORT uRet;
int i;
// be sure to init these to zero
WORD wsz=0, wEnc=0, wLen=0;
#ifdef DEBUG
// check BCtype first
switch(ifr)
{
case ifrNSF: /* RSL BG_CHK(npbc->bctype == SEND_CAPS); */ break;
case ifrNSS: BG_CHK(npbc->bctype == SEND_PARAMS); break;
case ifrNSC: BG_CHK(npbc->bctype == SEND_POLLREQ); break;
}
#endif //DEBUG
// RSL BG_CHK(npbc->wTotalSize >= sizeof(BC));
if(!fSendID)
{
// if we dont want to send the ID, save the ptrs/params of text id
// and zap it out of the BC struct before calling AWNSF
// We restore everything before exiting this function
wsz = npbc->wszTextId;
wLen = npbc->wTextIdLen;
wEnc = npbc->wTextEncoding;
npbc->wszTextId = npbc->wTextIdLen = npbc->wTextEncoding = 0;
}
if(uRet = BC_TO_NSX(pTG, ifr, npbc, fsFreePtr(pTG, npfs), (WORD) fsFreeSpace(pTG, npfs), &wNumFrames))
{
(MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> BCtoNSx returned error %d\r\n", uRet));
// go restore pointers if neccesary
goto done;
}
else if(wNumFrames)
{
LPLPFR rglpfr = (LPLPFR)fsFreePtr(pTG, npfs);
LPBYTE lpbLim = (LPBYTE)fsFreePtr(pTG, npfs);
for(i=0; i<(int)wNumFrames; i++)
{
(MyDebugPrint(pTG, LOG_ALL, "Created NSF/NSC, len=%d\r\n", rglpfr[i]->cb));
BG_CHK((LPBYTE)(rglpfr[i]) >= fsStart(pTG, npfs));
BG_CHK(rglpfr[i]->fif+rglpfr[i]->cb <= fsLim(pTG, npfs));
#ifndef NOCHALL
if(ifr==ifrNSF && i==0)
{
BG_CHK(rglpfr[i]->cb > 3);
pTG->uSavedChallengeLen = min(rglpfr[i]->cb-3, POLL_CHALLENGE_LEN);
_fmemcpy(pTG->bSavedChallenge, rglpfr[i]->fif+3, pTG->uSavedChallengeLen);
}
#endif //!NOCHALL
if(npfs->uNumFrames < MAXFRAMES)
{
npfs->rglpfr[npfs->uNumFrames++] = rglpfr[i];
lpbLim = max(lpbLim, rglpfr[i]->fif+rglpfr[i]->cb);
}
else { BG_CHK(FALSE); break; }
}
npfs->uFreeSpaceOff = (USHORT)(lpbLim - ((LPBYTE)(npfs->b)));
BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
}
else { BG_CHK(FALSE); }
done:
// restore TextId in BC, if we had zapped it out!
if(wsz) npbc->wszTextId = wsz;
if(wLen) npbc->wTextIdLen = wLen;
if(wEnc) npbc->wTextEncoding = wEnc;
return;
}
void CreateIDFrame(PThrdGlbl pTG, IFR ifr, NPRFS npfs, LPSTR szId, BOOL fStrip)
{
BYTE szTemp[IDFIFSIZE+2];
USHORT i, j;
NPFR npfr;
npfr = (NPFR) fsFreePtr(pTG, npfs);
if( fsFreeSpace(pTG, npfs) <= (sizeof(FRBASE)+IDFIFSIZE) ||
npfs->uNumFrames >= MAXFRAMES)
{
BG_CHK(FALSE);
return;
}
if(fStrip)
{
// CreateID strips non-numeric parts. Must send TSI when
// we do EFAX-to-EFAX in G3 mode. See bug#771
for(i=0, j=0; szId[i] && j<IDFIFSIZE; i++)
{
// copy over all numerics and NON-LEADING blanks
// throw away all leading blanks
if( (szId[i] >= '0' && szId[i] <= '9') ||
(szId[i] == ' ' && j != 0))
{
szTemp[j++] = szId[i];
}
// send + and - as space. At other end, when we get a
// single leading space convert that to +. Leave other spaces
// unmolested. This is so that EFAX-to-EFAX in G3 mode
// with canonical numbers, reply will work correctly
// see bug#771
if(szId[i] == '+' || szId[i] == '-')
{
szTemp[j++] = ' ';
}
}
szTemp[j++] = 0;
}
else
{
_fmemcpy(szTemp, szId, IDFIFSIZE);
szTemp[IDFIFSIZE] = 0;
}
(MyDebugPrint(pTG, LOG_ALL, "CreateID: Got<%s> Sent<%s>\r\n", (LPSTR)szId, (LPSTR)szTemp));
if(_fstrlen(szTemp))
{
CreateStupidReversedFIFs(pTG, npfr->fif, szTemp);
npfr->ifr = ifr;
npfr->cb = IDFIFSIZE;
npfs->rglpfr[npfs->uNumFrames++] = npfr;
npfs->uFreeSpaceOff += IDFIFSIZE+sizeof(FRBASE);
BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
}
else
{
(MyDebugPrint(pTG, LOG_ALL, "WARNING: %s ID is EMPTY. Not sending\r\n", (LPSTR)(fStrip ? "STRIPPED" : "ORIGINAL") ));
}
}
void CreateDISorDTC(PThrdGlbl pTG, IFR ifr, NPRFS npfs, NPBCFAX npbcFax, NPLLPARAMS npll)
{
USHORT uLen;
NPFR npfr;
if( fsFreeSpace(pTG, npfs) <= (sizeof(FRBASE)+sizeof(DIS)) ||
npfs->uNumFrames >= MAXFRAMES)
{
BG_CHK(FALSE);
return;
}
npfr = (NPFR) fsFreePtr(pTG, npfs);
uLen = SetupDISorDCSorDTC(pTG, (NPDIS)npfr->fif, npbcFax, npll, 0, npll->fECM64);
BG_CHK(uLen >= 3 && uLen <= 8);
// BG_CHK(npfr->fif[uLen-1] == 0); // send a final 0 byte
npfr->ifr = ifr;
npfr->cb = (BYTE) uLen;
npfs->rglpfr[npfs->uNumFrames++] = npfr;
npfs->uFreeSpaceOff += uLen+sizeof(FRBASE);
BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
}
VOID CreateNSSTSIDCS(PThrdGlbl pTG, NPPROT npProt, NPRFS npfs, USHORT uWhichDCS)
{
// uWhichDCS:: 0==1st DCS 1==after NoReply 2==afterFTT
NPBC npbc = (NPBC)&(npProt->SendParams);
BOOL fEfax;
// Use bigger buf. Avoid truncating Id before stripping alphas
char szTSI[MAXTOTALIDLEN + 2];
BG_CHK(npProt->fSendParamsInited);
BG_CHK(npbc->bctype==SEND_PARAMS);
BG_CHK(npbc->wTotalSize >= sizeof(BC));
BG_CHK(npProt->fllRecvCapsGot);
BG_CHK(npProt->fllSendParamsInited);
BG_CHK(npProt->fHWCapsInited);
/********** moved to the RECVCAPS point. see bug#731 ********************
if(uWhichDCS==0) // don't renegotiate after NoRely or FTT
{
NegotiateLowLevelParams(&npProt->llRecvCaps, &npProt->llSendParams,
npbc->Fax.AwRes, npbc->Fax.Encoding, &npProt->llNegot);
npProt->fllNegotiated = TRUE;
EnforceMaxSpeed(npProt);
}
*************************************************************************/
BG_CHK(npProt->fllNegotiated);
// don't print -- too slow
// (MyDebugPrint(pTG, "In CreateNSSTSIDCS after negotiation\r\n"));
// D_PrintBC(npbc, &npProt->llNegot);
ZeroRFS(pTG, npfs);
// Send only TSI-DCS or NSS-DCS. Never a need to send TSI with NSS
// (can bundle ID into message)
// extract ID
// BUGBUG RSL need to get from the Registry.
// GetTextId(npbc, szTSI, MAXTOTALIDLEN+1);
if (pTG->LocalID) {
strcpy (szTSI, pTG->LocalID);
}
#ifdef OEMNSF
if(fUsingOEMProt) // using OEM, not MS At Work NSSs
{
WORD wFlags;
BG_CHK(wOEMFlags);
wFlags = CreateOEMFrames(pTG, ifrNSS, 0, npbc, &npProt->llNegot, npfs);
BG_CHK(wFlags);
if(!(wFlags & OEMNSF_DONTSEND_TSI))
CreateIDFrame(pTG, ifrTSI, npfs, szTSI, TRUE); //STRIP alphas in TSI
if(!(wFlags & OEMNSF_DONTSEND_DCS))
CreateDCS(pTG, npfs, &(npbc->Fax), &npProt->llNegot);
}
else
#endif //OEMNSF
{
fEfax = (npbc->NSS.vMsgProtocol != 0);
// RSL no NSF
if(0)
{
// must be TRUE otheriwse we have negotaited ourselves into a corner here
BG_CHK(npProt->llNegot.fECM);
CreateNSForNSCorNSS(pTG, ifrNSS, npfs, npbc, FALSE); // no ID in NSS
}
else
{
// CreateID strips non-numeric parts. Must send TSI when
// we do EFAX-to-EFAX in G3 mode. See bug#771
if(_fstrlen(szTSI))
{
// This is for Snowball, as per bug#771
CreateIDFrame(pTG, ifrTSI, npfs, szTSI, FALSE); //RSL: DON'T STRIP alphas in TSI
}
}
CreateDCS(pTG, npfs, &(npbc->Fax), &npProt->llNegot);
BG_CHK((npbc->NSS.vMsgProtocol == 0) ||
(!npbc->Fax.AwRes && !npbc->Fax.Encoding));
}
}
void CreateDCS(PThrdGlbl pTG, NPRFS npfs, NPBCFAX npbcFax, NPLLPARAMS npll)
{
USHORT uLen;
NPFR npfr;
if( fsFreeSpace(pTG, npfs) <= (sizeof(FRBASE)+sizeof(DIS)) ||
npfs->uNumFrames >= MAXFRAMES)
{
BG_CHK(FALSE);
return;
}
npfr = (NPFR) fsFreePtr(pTG, npfs);
BG_CHK(npbcFax->fPublicPoll==0);
npbcFax->fPublicPoll = 0;
// the G3Poll bit *has* to be 0 in DCS
// else the OMNIFAX G77 and GT croak
// the PWD/SEP/SUB bits *have* to be 0 in DCS
// Baud rate, ECM and ECM frame size according to lowlevel negotiation
// everything else according to high level negotiation
uLen = SetupDISorDCSorDTC(pTG, (NPDIS)npfr->fif, npbcFax,
npll, npll->fECM, npll->fECM64);
BG_CHK(uLen >= 3 && uLen <= 8);
// BG_CHK(npfr->fif[uLen-1] == 0); // send a final 0 byte
// make sure that DCS we send is no longer than the DIS we receive.
// This should automatically be so
BG_CHK(pTG->ProtInst.uRemoteDISlen ? (uLen-1 <= pTG->ProtInst.uRemoteDISlen) : TRUE);
BG_CHK(pTG->ProtInst.uRemoteDTClen ? (uLen-1 <= pTG->ProtInst.uRemoteDTClen) : TRUE);
// If DCS is longer than the recvd DIS truncate the DCS to the same
// length as the DIS. (It should never be more than 1byte longer --
// because of the extra 0).
if(pTG->ProtInst.uRemoteDISlen && (pTG->ProtInst.uRemoteDISlen < uLen))
uLen = pTG->ProtInst.uRemoteDISlen;
else if(pTG->ProtInst.uRemoteDTClen && (pTG->ProtInst.uRemoteDTClen < uLen))
uLen = pTG->ProtInst.uRemoteDTClen;
npfr->ifr = ifrDCS;
npfr->cb = (BYTE) uLen;
npfs->rglpfr[npfs->uNumFrames++] = npfr;
npfs->uFreeSpaceOff += uLen+sizeof(FRBASE);
BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
}
#ifdef NSF_TEST_HOOKS
#pragma message("<<WARNING>> INCLUDING NSF TEST HOOKS")
BOOL NSFTestGetNSx (PThrdGlbl pTG, IFR ifr, LPBC lpbcIn,
LPBYTE lpbOut, WORD wMaxOut, LPWORD lpwNumFrame)
{
BOOL fRet=FALSE;
DWORD_PTR dwKey=ProfileOpen(DEF_BASEKEY, szNSFTEST, fREG_READ);
char rgchTmp32[32];
LPSTR lpsz=NULL;
UINT ucb,ucb0;
if (!dwKey) goto end;
switch(ifr)
{
case ifrNSF: lpsz = "NSF"; break;
case ifrNSS: lpsz = "NSS"; break;
case ifrNSC: lpsz = "NSC"; break;
default: BG_CHK(FALSE); goto end;
}
wsprintf(rgchTmp32, "Send%sFrameCount", (LPSTR) lpsz);
*lpwNumFrame = (WORD) ProfileGetInt(dwKey, rgchTmp32, 0, NULL);
if(!*lpwNumFrame) goto end;
// Save space for frame pointer array
ucb=sizeof(LPFR) * *lpwNumFrame;
if (wMaxOut <= ucb) goto end;
wsprintf(rgchTmp32, "Send%sFrames", (LPSTR) lpsz);
ucb0=ProfileGetData(dwKey, rgchTmp32, lpbOut+ucb, wMaxOut-ucb);
if (!ucb0) goto end;
#ifdef DEBUG
{
char rgchTmp64[64];
UINT u,v;
(MyDebugPrint(pTG, LOG_ERR, "\r\nTEST-NSF: Dump of %u send frame(s):\r\n",
(unsigned) *lpwNumFrame));
rgchTmp64[0]=0;
for (u=0,v=0;u<ucb0;u++)
{
v += wsprintf(rgchTmp64+v, " %02x", (unsigned) lpbOut[ucb+u]);
if ((v+8) >= sizeof(rgchTmp64))
{
(MyDebugPrint(pTG, LOG_ERR, "\t%s\r\n", (LPSTR) rgchTmp64));
v=0;
rgchTmp64[0]=0;
}
}
(MyDebugPrint(pTG, LOG_ERR, "\t%s\r\n", (LPSTR) rgchTmp64));
}
#endif
// Initialize frame pointer array
{
UINT u;
UINT ucbtot = ucb+ucb0;
for (u=0;u<*lpwNumFrame;u++)
{
LPFR lpfr = (LPFR) (lpbOut+ucb);
(MyDebugPrint(pTG, LOG_ERR, "NSFTest: u=%lu, ifr=%lu, cb=%lu, ucb=%lu\r\n",
(unsigned long) u,
(unsigned long) lpfr->ifr,
(unsigned long) lpfr->cb,
(unsigned long) ucb));
if (lpfr->ifr!=ifr) goto bad_frames;
if (lpfr->cb>100) // awnsfapi.h says max frame size=70.
goto bad_frames;
if ((ucb+sizeof(FRBASE)+lpfr->cb)>ucbtot)
goto bad_frames;
((LPFR *)(lpbOut))[u] = lpfr;
ucb+=sizeof(FRBASE)+lpfr->cb;
}
}
fRet=TRUE;
goto end;
bad_frames:
(MyDebugPrint(pTG, LOG_ERR, "TEST-NSF: Bad frames from registry\r\n"));
// fall through..
end:
if (dwKey) ProfileClose(dwKey);
if (!fRet) {(MyDebugPrint(pTG, LOG_ALL, "WARNING: NSFTestGetNSx FAILS!\r\n"));}
return fRet;
}
BOOL NSFTestPutNSx(PThrdGlbl pTG, IFR ifr, LPLPFR rglpfr, WORD wNumFrame,
LPBC lpbcOut, WORD wBCSize)
{
BOOL fRet=FALSE;
DWORD_PTR dwKey=ProfileOpen(DEF_BASEKEY, szNSFTEST, fREG_CREATE|fREG_WRITE);
char rgchTmp32[32];
char rgchTmp10[10];
BYTE rgbTmp256[256];
LPSTR lpsz=NULL;
UINT u;
UINT ucb=0;
if (!dwKey) goto end;
switch(ifr)
{
case ifrNSF: lpsz = "NSF"; break;
case ifrNSS: lpsz = "NSS"; break;
case ifrNSC: lpsz = "NSC"; break;
default: BG_CHK(FALSE); goto end;
}
// Tack frames together...
ucb=0;
for(u=0; u<wNumFrame; u++)
{
UINT uLen = sizeof(FRBASE)+rglpfr[u]->cb;
if ((ucb+uLen) > sizeof(rgbTmp256))
{
(MyDebugPrint(pTG, LOG_ERR, "<<WARNING>>NSFTEST: Out of space!\r\n"));
break;
}
_fmemcpy(rgbTmp256+ucb, (LPBYTE)rglpfr[u], uLen);
ucb+=uLen;
}
if(u)
{
wsprintf(rgchTmp32, "Recvd%sFrames", (LPSTR) lpsz);
if (!ProfileWriteData(dwKey, rgchTmp32, rgbTmp256, ucb)) goto end;
}
wsprintf(rgchTmp32, "Recvd%sFrameCount", (LPSTR) lpsz);
wsprintf(rgchTmp10, "%u", (unsigned) (u&0xff));
if (!ProfileWriteString(dwKey, rgchTmp32, rgchTmp10, FALSE)) goto end;
fRet=TRUE;
end:
if (dwKey) ProfileClose(dwKey);
if (!fRet) {(MyDebugPrint(pTG, LOG_ERR, "NSFTestPutNSx FAILS!\r\n"));}
return fRet;
}
#endif // NSF_TEST_HOOKS