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

  1. /***************************************************************************
  2. Name : SENDFR.C
  3. Comment :
  4. Functions: (see Prototypes just below)
  5. Copyright (c) 1993 Microsoft Corp.
  6. Revision Log
  7. Date Name Description
  8. -------- ----- ---------------------------------------------------------
  9. ***************************************************************************/
  10. #include "prep.h"
  11. #include "efaxcb.h"
  12. #include "protocol.h"
  13. ///RSL
  14. #include "glbproto.h"
  15. #define faxTlog(m) DEBUGMSG(ZONE_SENDFR, m)
  16. #define FILEID FILEID_SENDFR
  17. VOID BCtoNSFCSIDIS(PThrdGlbl pTG, NPRFS npfs, NPBC npbc, NPLLPARAMS npll)
  18. {
  19. // Use bigger buf. Avoid truncating Id before stripping alphas
  20. char szCSI[MAXTOTALIDLEN + 2];
  21. //BG_CHK(npbc->bctype==SEND_CAPS);
  22. //BG_CHK(npbc->wTotalSize >= sizeof(BC));
  23. ZeroRFS(pTG, npfs);
  24. // extract ID
  25. // GetTextId(npbc, szCSI, MAXTOTALIDLEN+1);
  26. if (pTG->LocalID) {
  27. strcpy (szCSI, pTG->LocalID);
  28. }
  29. #ifdef OEMNSF
  30. CreateOEMFrames(pTG, ifrNSF, OEMNSF_POSBEFORE, npbc, npll, npfs);
  31. #endif
  32. // RSL no NSF
  33. #if 0
  34. // Send MS NSFs IFF ECM is enabled
  35. if (1) /// RSL (pTG->ProtInst.llSendCaps.fECM)
  36. {
  37. // Now create MS NSx
  38. CreateNSForNSCorNSS(pTG, ifrNSF, npfs, npbc, FALSE); // NO id in NSF
  39. }
  40. else
  41. {
  42. // zap MMR out of our DIS
  43. npbc->Fax.Encoding &= (~MMR_DATA);
  44. }
  45. #endif
  46. #ifdef OEMNSF
  47. CreateOEMFrames(pTG, ifrNSF, OEMNSF_POSAFTER, npbc, npll, npfs);
  48. #endif
  49. if(_fstrlen(szCSI))
  50. CreateIDFrame(pTG, ifrCSI, npfs, szCSI, FALSE); // RSL: DON'T strip non-numerics for CSI
  51. CreateDISorDTC(pTG, ifrDIS, npfs, &npbc->Fax, npll);
  52. }
  53. VOID BCtoNSCCIGDTC(PThrdGlbl pTG, NPRFS npfs, NPBC npbc, NPLLPARAMS npll)
  54. {
  55. // Use bigger buf. Avoid truncating Id before stripping alphas
  56. char szCIG[MAXTOTALIDLEN + 2];
  57. BOOL fSkipDTC;
  58. BOOL fSkipCIG;
  59. BG_CHK(npbc->bctype==SEND_POLLREQ);
  60. BG_CHK(npbc->wTotalSize >= sizeof(BC));
  61. ZeroRFS(pTG, npfs);
  62. fSkipDTC = 0;
  63. fSkipCIG = 0;
  64. // extract ID
  65. GetTextId(npbc, szCIG, MAXTOTALIDLEN+1);
  66. #ifdef OEMNSF
  67. if(fUsingOEMProt)
  68. {
  69. WORD wFlags;
  70. BG_CHK(wOEMFlags);
  71. wFlags = CreateOEMFrames(pTG, ifrNSC, OEMNSF_POSBEFORE, npbc, npll, npfs);
  72. fSkipDTC = ((wFlags & OEMNSF_DONTSEND_DCS) != 0);
  73. fSkipCIG = ((wFlags & OEMNSF_DONTSEND_TSI) != 0);
  74. }
  75. else
  76. #endif
  77. {
  78. if(npbc->wNumPollReq)
  79. {
  80. // if we have NSC poll reqs send NSC _with_ our ID. This is reqd
  81. // for return addressing of response. See bug#6224 and 6675. In
  82. // this case CIG is redundant so dont send it.
  83. // NOTE: The real check we want to do is to see if we are polling
  84. // another AtWork amchine or a G3. This test is just a proxy. The
  85. // result is a residual bug that G3/blind-polls from IFAX-to-IFAX
  86. // will NOT be routed correctly, even though they could/should.
  87. // G3/Blind-polls from IFAX-to-G3 will never be routed correctly
  88. // so long as we rely on the pollee to do the routing, but IFAX
  89. // to G3 blind polls wil work if we replace the
  90. // if(wNumPollReq)
  91. // test with a
  92. // if(pollee is AtWork)
  93. //
  94. CreateNSForNSCorNSS(pTG, ifrNSC, npfs, npbc, TRUE); // ID in NSC with poll req
  95. fSkipCIG = TRUE;
  96. }
  97. else
  98. {
  99. // no NSC poll reqs, so only send our basic NSC
  100. // (ie. to advert capabilities) if we have ECM
  101. // Dont send our ID in this case. CIG is good enough
  102. if(pTG->ProtInst.llSendCaps.fECM)
  103. CreateNSForNSCorNSS(pTG, ifrNSC, npfs, npbc, FALSE); // no id in NSC w/o poll req
  104. }
  105. }
  106. if(!pTG->ProtInst.llSendCaps.fECM)
  107. {
  108. // zap MMR out of our DTC
  109. npbc->Fax.Encoding &= (~MMR_DATA);
  110. }
  111. if(!fSkipCIG && _fstrlen(szCIG))
  112. CreateIDFrame(pTG, ifrCIG, npfs, szCIG, TRUE);
  113. // Strip non-numerics for CIG. Our FULL ID (used for addressing the
  114. // response) is sent in the NSC if we have NSC poll requests, so the
  115. // CIG is only for G3 display purposes. Strip alphas to conform
  116. // to spec & cut it down to size
  117. if(!fSkipDTC)
  118. CreateDISorDTC(pTG, ifrDTC, npfs, &npbc->Fax, npll);
  119. }
  120. void CreateNSForNSCorNSS(PThrdGlbl pTG, IFR ifr, NPRFS npfs, NPBC npbc, BOOL fSendID)
  121. {
  122. WORD wNumFrames;
  123. USHORT uRet;
  124. int i;
  125. // be sure to init these to zero
  126. WORD wsz=0, wEnc=0, wLen=0;
  127. #ifdef DEBUG
  128. // check BCtype first
  129. switch(ifr)
  130. {
  131. case ifrNSF: /* RSL BG_CHK(npbc->bctype == SEND_CAPS); */ break;
  132. case ifrNSS: BG_CHK(npbc->bctype == SEND_PARAMS); break;
  133. case ifrNSC: BG_CHK(npbc->bctype == SEND_POLLREQ); break;
  134. }
  135. #endif //DEBUG
  136. // RSL BG_CHK(npbc->wTotalSize >= sizeof(BC));
  137. if(!fSendID)
  138. {
  139. // if we dont want to send the ID, save the ptrs/params of text id
  140. // and zap it out of the BC struct before calling AWNSF
  141. // We restore everything before exiting this function
  142. wsz = npbc->wszTextId;
  143. wLen = npbc->wTextIdLen;
  144. wEnc = npbc->wTextEncoding;
  145. npbc->wszTextId = npbc->wTextIdLen = npbc->wTextEncoding = 0;
  146. }
  147. if(uRet = BC_TO_NSX(pTG, ifr, npbc, fsFreePtr(pTG, npfs), (WORD) fsFreeSpace(pTG, npfs), &wNumFrames))
  148. {
  149. (MyDebugPrint(pTG, LOG_ERR, "<<ERROR>> BCtoNSx returned error %d\r\n", uRet));
  150. // go restore pointers if neccesary
  151. goto done;
  152. }
  153. else if(wNumFrames)
  154. {
  155. LPLPFR rglpfr = (LPLPFR)fsFreePtr(pTG, npfs);
  156. LPBYTE lpbLim = (LPBYTE)fsFreePtr(pTG, npfs);
  157. for(i=0; i<(int)wNumFrames; i++)
  158. {
  159. (MyDebugPrint(pTG, LOG_ALL, "Created NSF/NSC, len=%d\r\n", rglpfr[i]->cb));
  160. BG_CHK((LPBYTE)(rglpfr[i]) >= fsStart(pTG, npfs));
  161. BG_CHK(rglpfr[i]->fif+rglpfr[i]->cb <= fsLim(pTG, npfs));
  162. #ifndef NOCHALL
  163. if(ifr==ifrNSF && i==0)
  164. {
  165. BG_CHK(rglpfr[i]->cb > 3);
  166. pTG->uSavedChallengeLen = min(rglpfr[i]->cb-3, POLL_CHALLENGE_LEN);
  167. _fmemcpy(pTG->bSavedChallenge, rglpfr[i]->fif+3, pTG->uSavedChallengeLen);
  168. }
  169. #endif //!NOCHALL
  170. if(npfs->uNumFrames < MAXFRAMES)
  171. {
  172. npfs->rglpfr[npfs->uNumFrames++] = rglpfr[i];
  173. lpbLim = max(lpbLim, rglpfr[i]->fif+rglpfr[i]->cb);
  174. }
  175. else { BG_CHK(FALSE); break; }
  176. }
  177. npfs->uFreeSpaceOff = (USHORT)(lpbLim - ((LPBYTE)(npfs->b)));
  178. BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
  179. }
  180. else { BG_CHK(FALSE); }
  181. done:
  182. // restore TextId in BC, if we had zapped it out!
  183. if(wsz) npbc->wszTextId = wsz;
  184. if(wLen) npbc->wTextIdLen = wLen;
  185. if(wEnc) npbc->wTextEncoding = wEnc;
  186. return;
  187. }
  188. void CreateIDFrame(PThrdGlbl pTG, IFR ifr, NPRFS npfs, LPSTR szId, BOOL fStrip)
  189. {
  190. BYTE szTemp[IDFIFSIZE+2];
  191. USHORT i, j;
  192. NPFR npfr;
  193. npfr = (NPFR) fsFreePtr(pTG, npfs);
  194. if( fsFreeSpace(pTG, npfs) <= (sizeof(FRBASE)+IDFIFSIZE) ||
  195. npfs->uNumFrames >= MAXFRAMES)
  196. {
  197. BG_CHK(FALSE);
  198. return;
  199. }
  200. if(fStrip)
  201. {
  202. // CreateID strips non-numeric parts. Must send TSI when
  203. // we do EFAX-to-EFAX in G3 mode. See bug#771
  204. for(i=0, j=0; szId[i] && j<IDFIFSIZE; i++)
  205. {
  206. // copy over all numerics and NON-LEADING blanks
  207. // throw away all leading blanks
  208. if( (szId[i] >= '0' && szId[i] <= '9') ||
  209. (szId[i] == ' ' && j != 0))
  210. {
  211. szTemp[j++] = szId[i];
  212. }
  213. // send + and - as space. At other end, when we get a
  214. // single leading space convert that to +. Leave other spaces
  215. // unmolested. This is so that EFAX-to-EFAX in G3 mode
  216. // with canonical numbers, reply will work correctly
  217. // see bug#771
  218. if(szId[i] == '+' || szId[i] == '-')
  219. {
  220. szTemp[j++] = ' ';
  221. }
  222. }
  223. szTemp[j++] = 0;
  224. }
  225. else
  226. {
  227. _fmemcpy(szTemp, szId, IDFIFSIZE);
  228. szTemp[IDFIFSIZE] = 0;
  229. }
  230. (MyDebugPrint(pTG, LOG_ALL, "CreateID: Got<%s> Sent<%s>\r\n", (LPSTR)szId, (LPSTR)szTemp));
  231. if(_fstrlen(szTemp))
  232. {
  233. CreateStupidReversedFIFs(pTG, npfr->fif, szTemp);
  234. npfr->ifr = ifr;
  235. npfr->cb = IDFIFSIZE;
  236. npfs->rglpfr[npfs->uNumFrames++] = npfr;
  237. npfs->uFreeSpaceOff += IDFIFSIZE+sizeof(FRBASE);
  238. BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
  239. }
  240. else
  241. {
  242. (MyDebugPrint(pTG, LOG_ALL, "WARNING: %s ID is EMPTY. Not sending\r\n", (LPSTR)(fStrip ? "STRIPPED" : "ORIGINAL") ));
  243. }
  244. }
  245. void CreateDISorDTC(PThrdGlbl pTG, IFR ifr, NPRFS npfs, NPBCFAX npbcFax, NPLLPARAMS npll)
  246. {
  247. USHORT uLen;
  248. NPFR npfr;
  249. if( fsFreeSpace(pTG, npfs) <= (sizeof(FRBASE)+sizeof(DIS)) ||
  250. npfs->uNumFrames >= MAXFRAMES)
  251. {
  252. BG_CHK(FALSE);
  253. return;
  254. }
  255. npfr = (NPFR) fsFreePtr(pTG, npfs);
  256. uLen = SetupDISorDCSorDTC(pTG, (NPDIS)npfr->fif, npbcFax, npll, 0, npll->fECM64);
  257. BG_CHK(uLen >= 3 && uLen <= 8);
  258. // BG_CHK(npfr->fif[uLen-1] == 0); // send a final 0 byte
  259. npfr->ifr = ifr;
  260. npfr->cb = (BYTE) uLen;
  261. npfs->rglpfr[npfs->uNumFrames++] = npfr;
  262. npfs->uFreeSpaceOff += uLen+sizeof(FRBASE);
  263. BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
  264. }
  265. VOID CreateNSSTSIDCS(PThrdGlbl pTG, NPPROT npProt, NPRFS npfs, USHORT uWhichDCS)
  266. {
  267. // uWhichDCS:: 0==1st DCS 1==after NoReply 2==afterFTT
  268. NPBC npbc = (NPBC)&(npProt->SendParams);
  269. BOOL fEfax;
  270. // Use bigger buf. Avoid truncating Id before stripping alphas
  271. char szTSI[MAXTOTALIDLEN + 2];
  272. BG_CHK(npProt->fSendParamsInited);
  273. BG_CHK(npbc->bctype==SEND_PARAMS);
  274. BG_CHK(npbc->wTotalSize >= sizeof(BC));
  275. BG_CHK(npProt->fllRecvCapsGot);
  276. BG_CHK(npProt->fllSendParamsInited);
  277. BG_CHK(npProt->fHWCapsInited);
  278. /********** moved to the RECVCAPS point. see bug#731 ********************
  279. if(uWhichDCS==0) // don't renegotiate after NoRely or FTT
  280. {
  281. NegotiateLowLevelParams(&npProt->llRecvCaps, &npProt->llSendParams,
  282. npbc->Fax.AwRes, npbc->Fax.Encoding, &npProt->llNegot);
  283. npProt->fllNegotiated = TRUE;
  284. EnforceMaxSpeed(npProt);
  285. }
  286. *************************************************************************/
  287. BG_CHK(npProt->fllNegotiated);
  288. // don't print -- too slow
  289. // (MyDebugPrint(pTG, "In CreateNSSTSIDCS after negotiation\r\n"));
  290. // D_PrintBC(npbc, &npProt->llNegot);
  291. ZeroRFS(pTG, npfs);
  292. // Send only TSI-DCS or NSS-DCS. Never a need to send TSI with NSS
  293. // (can bundle ID into message)
  294. // extract ID
  295. // BUGBUG RSL need to get from the Registry.
  296. // GetTextId(npbc, szTSI, MAXTOTALIDLEN+1);
  297. if (pTG->LocalID) {
  298. strcpy (szTSI, pTG->LocalID);
  299. }
  300. #ifdef OEMNSF
  301. if(fUsingOEMProt) // using OEM, not MS At Work NSSs
  302. {
  303. WORD wFlags;
  304. BG_CHK(wOEMFlags);
  305. wFlags = CreateOEMFrames(pTG, ifrNSS, 0, npbc, &npProt->llNegot, npfs);
  306. BG_CHK(wFlags);
  307. if(!(wFlags & OEMNSF_DONTSEND_TSI))
  308. CreateIDFrame(pTG, ifrTSI, npfs, szTSI, TRUE); //STRIP alphas in TSI
  309. if(!(wFlags & OEMNSF_DONTSEND_DCS))
  310. CreateDCS(pTG, npfs, &(npbc->Fax), &npProt->llNegot);
  311. }
  312. else
  313. #endif //OEMNSF
  314. {
  315. fEfax = (npbc->NSS.vMsgProtocol != 0);
  316. // RSL no NSF
  317. if(0)
  318. {
  319. // must be TRUE otheriwse we have negotaited ourselves into a corner here
  320. BG_CHK(npProt->llNegot.fECM);
  321. CreateNSForNSCorNSS(pTG, ifrNSS, npfs, npbc, FALSE); // no ID in NSS
  322. }
  323. else
  324. {
  325. // CreateID strips non-numeric parts. Must send TSI when
  326. // we do EFAX-to-EFAX in G3 mode. See bug#771
  327. if(_fstrlen(szTSI))
  328. {
  329. // This is for Snowball, as per bug#771
  330. CreateIDFrame(pTG, ifrTSI, npfs, szTSI, FALSE); //RSL: DON'T STRIP alphas in TSI
  331. }
  332. }
  333. CreateDCS(pTG, npfs, &(npbc->Fax), &npProt->llNegot);
  334. BG_CHK((npbc->NSS.vMsgProtocol == 0) ||
  335. (!npbc->Fax.AwRes && !npbc->Fax.Encoding));
  336. }
  337. }
  338. void CreateDCS(PThrdGlbl pTG, NPRFS npfs, NPBCFAX npbcFax, NPLLPARAMS npll)
  339. {
  340. USHORT uLen;
  341. NPFR npfr;
  342. if( fsFreeSpace(pTG, npfs) <= (sizeof(FRBASE)+sizeof(DIS)) ||
  343. npfs->uNumFrames >= MAXFRAMES)
  344. {
  345. BG_CHK(FALSE);
  346. return;
  347. }
  348. npfr = (NPFR) fsFreePtr(pTG, npfs);
  349. BG_CHK(npbcFax->fPublicPoll==0);
  350. npbcFax->fPublicPoll = 0;
  351. // the G3Poll bit *has* to be 0 in DCS
  352. // else the OMNIFAX G77 and GT croak
  353. // the PWD/SEP/SUB bits *have* to be 0 in DCS
  354. // Baud rate, ECM and ECM frame size according to lowlevel negotiation
  355. // everything else according to high level negotiation
  356. uLen = SetupDISorDCSorDTC(pTG, (NPDIS)npfr->fif, npbcFax,
  357. npll, npll->fECM, npll->fECM64);
  358. BG_CHK(uLen >= 3 && uLen <= 8);
  359. // BG_CHK(npfr->fif[uLen-1] == 0); // send a final 0 byte
  360. // make sure that DCS we send is no longer than the DIS we receive.
  361. // This should automatically be so
  362. BG_CHK(pTG->ProtInst.uRemoteDISlen ? (uLen-1 <= pTG->ProtInst.uRemoteDISlen) : TRUE);
  363. BG_CHK(pTG->ProtInst.uRemoteDTClen ? (uLen-1 <= pTG->ProtInst.uRemoteDTClen) : TRUE);
  364. // If DCS is longer than the recvd DIS truncate the DCS to the same
  365. // length as the DIS. (It should never be more than 1byte longer --
  366. // because of the extra 0).
  367. if(pTG->ProtInst.uRemoteDISlen && (pTG->ProtInst.uRemoteDISlen < uLen))
  368. uLen = pTG->ProtInst.uRemoteDISlen;
  369. else if(pTG->ProtInst.uRemoteDTClen && (pTG->ProtInst.uRemoteDTClen < uLen))
  370. uLen = pTG->ProtInst.uRemoteDTClen;
  371. npfr->ifr = ifrDCS;
  372. npfr->cb = (BYTE) uLen;
  373. npfs->rglpfr[npfs->uNumFrames++] = npfr;
  374. npfs->uFreeSpaceOff += uLen+sizeof(FRBASE);
  375. BG_CHK(npfs->uFreeSpaceOff <= fsSize(pTG, npfs) && npfs->uNumFrames <= MAXFRAMES);
  376. }
  377. #ifdef NSF_TEST_HOOKS
  378. #pragma message("<<WARNING>> INCLUDING NSF TEST HOOKS")
  379. BOOL NSFTestGetNSx (PThrdGlbl pTG, IFR ifr, LPBC lpbcIn,
  380. LPBYTE lpbOut, WORD wMaxOut, LPWORD lpwNumFrame)
  381. {
  382. BOOL fRet=FALSE;
  383. DWORD_PTR dwKey=ProfileOpen(DEF_BASEKEY, szNSFTEST, fREG_READ);
  384. char rgchTmp32[32];
  385. LPSTR lpsz=NULL;
  386. UINT ucb,ucb0;
  387. if (!dwKey) goto end;
  388. switch(ifr)
  389. {
  390. case ifrNSF: lpsz = "NSF"; break;
  391. case ifrNSS: lpsz = "NSS"; break;
  392. case ifrNSC: lpsz = "NSC"; break;
  393. default: BG_CHK(FALSE); goto end;
  394. }
  395. wsprintf(rgchTmp32, "Send%sFrameCount", (LPSTR) lpsz);
  396. *lpwNumFrame = (WORD) ProfileGetInt(dwKey, rgchTmp32, 0, NULL);
  397. if(!*lpwNumFrame) goto end;
  398. // Save space for frame pointer array
  399. ucb=sizeof(LPFR) * *lpwNumFrame;
  400. if (wMaxOut <= ucb) goto end;
  401. wsprintf(rgchTmp32, "Send%sFrames", (LPSTR) lpsz);
  402. ucb0=ProfileGetData(dwKey, rgchTmp32, lpbOut+ucb, wMaxOut-ucb);
  403. if (!ucb0) goto end;
  404. #ifdef DEBUG
  405. {
  406. char rgchTmp64[64];
  407. UINT u,v;
  408. (MyDebugPrint(pTG, LOG_ERR, "\r\nTEST-NSF: Dump of %u send frame(s):\r\n",
  409. (unsigned) *lpwNumFrame));
  410. rgchTmp64[0]=0;
  411. for (u=0,v=0;u<ucb0;u++)
  412. {
  413. v += wsprintf(rgchTmp64+v, " %02x", (unsigned) lpbOut[ucb+u]);
  414. if ((v+8) >= sizeof(rgchTmp64))
  415. {
  416. (MyDebugPrint(pTG, LOG_ERR, "\t%s\r\n", (LPSTR) rgchTmp64));
  417. v=0;
  418. rgchTmp64[0]=0;
  419. }
  420. }
  421. (MyDebugPrint(pTG, LOG_ERR, "\t%s\r\n", (LPSTR) rgchTmp64));
  422. }
  423. #endif
  424. // Initialize frame pointer array
  425. {
  426. UINT u;
  427. UINT ucbtot = ucb+ucb0;
  428. for (u=0;u<*lpwNumFrame;u++)
  429. {
  430. LPFR lpfr = (LPFR) (lpbOut+ucb);
  431. (MyDebugPrint(pTG, LOG_ERR, "NSFTest: u=%lu, ifr=%lu, cb=%lu, ucb=%lu\r\n",
  432. (unsigned long) u,
  433. (unsigned long) lpfr->ifr,
  434. (unsigned long) lpfr->cb,
  435. (unsigned long) ucb));
  436. if (lpfr->ifr!=ifr) goto bad_frames;
  437. if (lpfr->cb>100) // awnsfapi.h says max frame size=70.
  438. goto bad_frames;
  439. if ((ucb+sizeof(FRBASE)+lpfr->cb)>ucbtot)
  440. goto bad_frames;
  441. ((LPFR *)(lpbOut))[u] = lpfr;
  442. ucb+=sizeof(FRBASE)+lpfr->cb;
  443. }
  444. }
  445. fRet=TRUE;
  446. goto end;
  447. bad_frames:
  448. (MyDebugPrint(pTG, LOG_ERR, "TEST-NSF: Bad frames from registry\r\n"));
  449. // fall through..
  450. end:
  451. if (dwKey) ProfileClose(dwKey);
  452. if (!fRet) {(MyDebugPrint(pTG, LOG_ALL, "WARNING: NSFTestGetNSx FAILS!\r\n"));}
  453. return fRet;
  454. }
  455. BOOL NSFTestPutNSx(PThrdGlbl pTG, IFR ifr, LPLPFR rglpfr, WORD wNumFrame,
  456. LPBC lpbcOut, WORD wBCSize)
  457. {
  458. BOOL fRet=FALSE;
  459. DWORD_PTR dwKey=ProfileOpen(DEF_BASEKEY, szNSFTEST, fREG_CREATE|fREG_WRITE);
  460. char rgchTmp32[32];
  461. char rgchTmp10[10];
  462. BYTE rgbTmp256[256];
  463. LPSTR lpsz=NULL;
  464. UINT u;
  465. UINT ucb=0;
  466. if (!dwKey) goto end;
  467. switch(ifr)
  468. {
  469. case ifrNSF: lpsz = "NSF"; break;
  470. case ifrNSS: lpsz = "NSS"; break;
  471. case ifrNSC: lpsz = "NSC"; break;
  472. default: BG_CHK(FALSE); goto end;
  473. }
  474. // Tack frames together...
  475. ucb=0;
  476. for(u=0; u<wNumFrame; u++)
  477. {
  478. UINT uLen = sizeof(FRBASE)+rglpfr[u]->cb;
  479. if ((ucb+uLen) > sizeof(rgbTmp256))
  480. {
  481. (MyDebugPrint(pTG, LOG_ERR, "<<WARNING>>NSFTEST: Out of space!\r\n"));
  482. break;
  483. }
  484. _fmemcpy(rgbTmp256+ucb, (LPBYTE)rglpfr[u], uLen);
  485. ucb+=uLen;
  486. }
  487. if(u)
  488. {
  489. wsprintf(rgchTmp32, "Recvd%sFrames", (LPSTR) lpsz);
  490. if (!ProfileWriteData(dwKey, rgchTmp32, rgbTmp256, ucb)) goto end;
  491. }
  492. wsprintf(rgchTmp32, "Recvd%sFrameCount", (LPSTR) lpsz);
  493. wsprintf(rgchTmp10, "%u", (unsigned) (u&0xff));
  494. if (!ProfileWriteString(dwKey, rgchTmp32, rgchTmp10, FALSE)) goto end;
  495. fRet=TRUE;
  496. end:
  497. if (dwKey) ProfileClose(dwKey);
  498. if (!fRet) {(MyDebugPrint(pTG, LOG_ERR, "NSFTestPutNSx FAILS!\r\n"));}
  499. return fRet;
  500. }
  501. #endif // NSF_TEST_HOOKS