/*************************************************************************** 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, "<> 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= '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("<> 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= 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; ucb; if ((ucb+uLen) > sizeof(rgbTmp256)) { (MyDebugPrint(pTG, LOG_ERR, "<>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