Leaked source code of windows server 2003
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.

3505 lines
111 KiB

  1. /***************************************************************************
  2. Name : IDENTIFY.C
  3. Comment : Identifying modems
  4. Copyright (c) Microsoft Corp. 1991, 1992, 1993
  5. Revision Log
  6. Num Date Name Description
  7. --- -------- ---------- -----------------------------------------------
  8. ***************************************************************************/
  9. #define USE_DEBUG_CONTEXT DEBUG_CONTEXT_T30_CLASS1
  10. #include "prep.h"
  11. #include "modemint.h"
  12. //#include "fcomint.h"
  13. #include "fdebug.h"
  14. #include "awmodem.h"
  15. #include "adaptive.h"
  16. ///RSL
  17. #include "glbproto.h"
  18. #define BIGTEMPSIZE 250
  19. #include "inifile.h"
  20. char szModemFaxClasses[] = "ModemFaxClasses";
  21. char szModemSendSpeeds[] = "ModemSendSpeeds";
  22. char szModemRecvSpeeds[] = "ModemRecvSpeeds";
  23. char szModemId[] = "ModemId";
  24. char szModemIdCmd[] = "ModemIdCmd";
  25. char szClass0ModemId[] = "Class0ModemId";
  26. char szClass2ModemId[] = "Class2ModemId";
  27. char szClass20ModemId[] = "Class2.0ModemId";
  28. char szResetCommand[] = "ResetCommand";
  29. char szResetCommandGenerated[] = "ResetCommandGenerated";
  30. char szSetupCommand[] = "SetupCommand";
  31. char szSetupCommandGenerated[] = "SetupCommandGenerated";
  32. char szExitCommand[] = "ExitCommand";
  33. char szPreDialCommand[] = "PreDialCommand";
  34. char szPreAnswerCommand[]= "PreAnswerCommand";
  35. // RSL new UNIMODEM INF settings (FAX GENERIC)
  36. char szHardwareFlowControl[] = "HardwareFlowControl";
  37. char szSerialSpeedInit[] = "SerialSpeedInit";
  38. char szSerialSpeedConnect[] = "SerialSpeedConnect";
  39. char szAdaptiveAnswerEnable[] = "AdaptiveAnswerEnable";
  40. // new ADAPTIVE INF file (FAX ADAPTIVE)
  41. char szResponsesKeyName[] = "ResponsesKeyName=";
  42. char szResponsesKeyName2[] = "ResponsesKeyName";
  43. char szAdaptiveRecordUnique[] = "AdaptiveRecordUnique";
  44. char szAdaptiveCodeId[] = "AdaptiveCodeId";
  45. char szFaxClass[] = "FaxClass";
  46. char szAnswerCommand[] = "AnswerCommand";
  47. char szModemResponseFaxDetect[] = "ModemResponseFaxDetect";
  48. char szModemResponseDataDetect[] = "ModemResponseDataDetect";
  49. char szSerialSpeedFaxDetect[] = "SerialSpeedFaxDetect";
  50. char szSerialSpeedDataDetect[] = "SerialSpeedDataDetect";
  51. char szHostCommandFaxDetect[] = "HostCommandFaxDetect";
  52. char szHostCommandDataDetect[] = "HostCommandDataDetect";
  53. char szModemResponseFaxConnect[] = "ModemResponseFaxConnect";
  54. char szModemResponseDataConnect[] = "ModemResponseDataConnect";
  55. // how was the Modem Key created
  56. char szModemKeyCreationId[] = "ModemKeyCreationId";
  57. #define NUM_CL0IDCMDS 7
  58. #define NUM_CL2IDCMDS 3
  59. #define NUM_CL20IDCMDS 3
  60. #define LEN_CL0IDCMDS 5
  61. #define LEN_CL2IDCMDS 9
  62. #define LEN_CL20IDCMDS 8
  63. USHORT iModemFigureOutCmdsExt(PThrdGlbl pTG);
  64. BOOL iModemCopyOEMInfo(PThrdGlbl pTG);
  65. void SmashCapsAccordingToSettings(PThrdGlbl pTG);
  66. NPSTR szClass0IdCmds[NUM_CL0IDCMDS] =
  67. {
  68. "ATI0\r",
  69. "ATI1\r",
  70. "ATI2\r",
  71. "ATI3\r",
  72. "ATI4\r",
  73. "ATI5\r",
  74. "ATI6\r"
  75. };
  76. NPSTR szClass2IdCmds[NUM_CL2IDCMDS] =
  77. {
  78. "AT+FMFR?\r",
  79. "AT+FMDL?\r",
  80. "AT+FREV?\r"
  81. };
  82. NPSTR szClass20IdCmds[NUM_CL20IDCMDS] =
  83. {
  84. "AT+FMI?\r",
  85. "AT+FMM?\r",
  86. "AT+FMR?\r"
  87. };
  88. typedef struct {
  89. USHORT uGoClass, //@ The fax class the modem need to be put on before using the id commands.
  90. uNum, //@ The number of strings (commands) in the command table.
  91. uLen; //@ The maximum length (required buffer size) in the command table.
  92. //@ (including space for a terminating NULL char).
  93. NPSTR *CmdTable; //@ An array of strings each containing a modem id command.
  94. NPSTR szIniEntry; //@ The name of the registry value in which the resulting
  95. //@ is should be saved ("Class0ModemId", "Class2ModemId", "Class2.0ModemId")
  96. } GETIDSTRUCT, near* NPGETIDSTRUCT;
  97. GETIDSTRUCT GetIdTable[3] =
  98. {
  99. { 0, NUM_CL0IDCMDS, LEN_CL0IDCMDS, szClass0IdCmds, szClass0ModemId },
  100. { 2, NUM_CL2IDCMDS, LEN_CL2IDCMDS, szClass2IdCmds, szClass2ModemId },
  101. { GOCLASS2_0, NUM_CL20IDCMDS, LEN_CL20IDCMDS, szClass20IdCmds, szClass20ModemId }
  102. };
  103. #define MAXCMDSIZE 128
  104. #define MAXIDSIZE 128
  105. #define RESPONSEBUFSIZE 256
  106. #define SMALLTEMPSIZE 80
  107. #define TMPSTRINGBUFSIZE (8*MAXCMDSIZE+MAXIDSIZE+RESPONSEBUFSIZE+2*SMALLTEMPSIZE+12)
  108. // Enough space for all the lpszs below.
  109. BOOL imodem_alloc_tmp_strings(PThrdGlbl pTG);
  110. void imodem_free_tmp_strings(PThrdGlbl pTG);
  111. void imodem_clear_tmp_settings(PThrdGlbl pTG);
  112. ///////////////////////////////////////////////////////////////////////////////////////
  113. // Function:
  114. // IsCacheIntDirty
  115. //
  116. // Purpose:
  117. // This function verifies if the cached settings we have
  118. // under HKLM\Sw\Ms\Fax\TAPIDevices is the same as the setting
  119. // under Unimodem's key:
  120. // HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E96D-E325-11CE-BFC1-08002BE10318}
  121. // If this setting is different it means that the modem driver was
  122. // updated and we have to re-install the modem and thus update our
  123. // cache.
  124. // The function validates a numeric setting, which is actually stored
  125. // as a REG_SZ in the registry and converted to UINT.
  126. //
  127. // Params:
  128. // ULONG_PTR UnimodemFaxKey: An open key to Unimodem's registry,
  129. // retrieved from a call to ProfileOpen.
  130. // LPSTR szSetting: The setting to check, this is the same
  131. // as appears in the docs (i.e. "FixModemClass").
  132. // UINT uCachedValue: Our cached value, to be compared with what's
  133. // read from Unimodem's registry.
  134. //
  135. // Return Value:
  136. // TRUE - Cached value does not match Unimodem's value, need re-installation
  137. // FALSE - Cache is not dirty, OK to continue.
  138. //
  139. // Author:
  140. // Mooly Beery (MoolyB) 14-Nov-2001
  141. ///////////////////////////////////////////////////////////////////////////////////////
  142. BOOL IsCacheIntDirty(ULONG_PTR UnimodemFaxKey, LPSTR szSetting,UINT uCachedValue)
  143. {
  144. BOOL fRet = FALSE;
  145. UINT uUnimodemSetting = 0;
  146. BOOL fExist = FALSE;
  147. DEBUG_FUNCTION_NAME(("IsCacheIntDirty"));
  148. if (UnimodemFaxKey)
  149. {
  150. uUnimodemSetting = ProfileGetInt(UnimodemFaxKey, szSetting, 0, &fExist);
  151. if (!fExist)
  152. {
  153. DebugPrintEx(DEBUG_MSG, "Modem does not have a %s section in its Fax INF section",szSetting);
  154. }
  155. else
  156. {
  157. if (uUnimodemSetting!=uCachedValue)
  158. {
  159. fRet = TRUE;
  160. }
  161. }
  162. }
  163. return fRet;
  164. }
  165. ///////////////////////////////////////////////////////////////////////////////////////
  166. // Function:
  167. // IsCacheStringDirty
  168. //
  169. // Purpose:
  170. // This function verifies if the cached settings we have
  171. // under HKLM\Sw\Ms\Fax\TAPIDevices is the same as the setting
  172. // under Unimodem's key:
  173. // HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E96D-E325-11CE-BFC1-08002BE10318}
  174. // If this setting is different it means that the modem driver was
  175. // updated and we have to re-install the modem and thus update our
  176. // cache.
  177. // The function validates a string setting.
  178. //
  179. // Params:
  180. // ULONG_PTR UnimodemFaxKey: An open key to Unimodem's registry,
  181. // retrieved from a call to ProfileOpen.
  182. // LPSTR szSetting: The setting to check, this is the same
  183. // as appears in the docs (i.e. "FixModemClass").
  184. // LPSTR szCachedValue: Our cached value, to be compared with what's
  185. // read from Unimodem's registry.
  186. //
  187. // Return Value:
  188. // TRUE - Cached value does not match Unimodem's value, need re-installation
  189. // FALSE - Cache is not dirty, OK to continue.
  190. //
  191. // Author:
  192. // Mooly Beery (MoolyB) 14-Nov-2001
  193. ///////////////////////////////////////////////////////////////////////////////////////
  194. BOOL IsCacheStringDirty(ULONG_PTR UnimodemFaxKey, LPSTR szSetting,LPSTR szCachedValue)
  195. {
  196. BOOL fRet = FALSE;
  197. UINT uLen = 0;
  198. char szUnimodemSetting[MAXCMDSIZE] = {0};
  199. DEBUG_FUNCTION_NAME(("IsCacheStringDirty"));
  200. if (UnimodemFaxKey)
  201. {
  202. uLen = ProfileGetString(UnimodemFaxKey,szSetting,NULL,szUnimodemSetting,MAXCMDSIZE-1);
  203. if (uLen==0)
  204. {
  205. DebugPrintEx(DEBUG_MSG, "Modem does not have a %s section in its Fax INF section",szSetting);
  206. }
  207. else
  208. {
  209. // szCachedValue has <cr> at the end, so don't include the <cr> in the compare
  210. if (strncmp(szUnimodemSetting, szCachedValue, max(strlen(szUnimodemSetting), strlen(szCachedValue)-1)))
  211. {
  212. fRet = TRUE;
  213. }
  214. }
  215. }
  216. return fRet;
  217. }
  218. BOOL
  219. imodem_list_get_str(
  220. PThrdGlbl pTG,
  221. ULONG_PTR KeyList[10],
  222. LPSTR lpszName,
  223. LPSTR lpszCmdBuf,
  224. UINT cbMax,
  225. BOOL fCmd);
  226. BOOL imodem_get_str(PThrdGlbl pTG, ULONG_PTR dwKey, LPSTR lpszName, LPSTR lpszCmdBuf, UINT cbMax,
  227. BOOL fCmd);
  228. BOOL SearchInfFile(PThrdGlbl pTG, LPSTR lpstrFile, LPSTR lpstr1, LPSTR lpstr2, LPSTR lpstr3, DWORD_PTR dwLocalKey);
  229. void CheckAwmodemInf(PThrdGlbl pTG);
  230. void ToCaps(LPBYTE lpb);
  231. BOOL iModemGetCurrentModemInfo(PThrdGlbl pTG);
  232. BOOL iModemSaveCurrentModemInfo(PThrdGlbl pTG);
  233. USHORT EndWithCR( LPSTR sz, USHORT uLen)
  234. {
  235. if(uLen)
  236. {
  237. // Check if the string is terminated with a \r
  238. if(sz[uLen-1] != '\r')
  239. {
  240. // add a \r
  241. sz[uLen++] = '\r';
  242. sz[uLen] = 0;
  243. }
  244. }
  245. return uLen;
  246. }
  247. BOOL RemoveCR( LPSTR sz )
  248. {
  249. DWORD len;
  250. if (!sz)
  251. {
  252. return FALSE;
  253. }
  254. len = strlen(sz);
  255. if (len == 0)
  256. {
  257. return FALSE;
  258. }
  259. if (sz[len-1] == '\r')
  260. {
  261. sz[len-1] = 0;
  262. }
  263. return TRUE;
  264. }
  265. //@
  266. //@ Sends an Id command to the modem and returns the resulting id string.
  267. //@
  268. USHORT GetIdResp(PThrdGlbl pTG, LPSTR szSend, USHORT uSendLen, LPBYTE lpbRespOut, USHORT cbMaxOut)
  269. {
  270. USHORT uRespLen;
  271. DEBUG_FUNCTION_NAME(("GetIdResp"));
  272. DebugPrintEx(DEBUG_MSG,"Want Id for (%s)", (LPSTR)szSend);
  273. pTG->fMegaHertzHack = TRUE;
  274. //@
  275. //@ Send the id command to the modem and wait for a response followed by OK or ERROR.
  276. //@ On return pTG->bLastReply contains the last modem response before the OK or ERROR.
  277. //@
  278. OfflineDialog2(pTG, (LPSTR)szSend, uSendLen, cbszOK, cbszERROR);
  279. pTG->fMegaHertzHack=FALSE;
  280. // sometimes we don't get the OK so try to parse what we got anyway
  281. DebugPrintEx(DEBUG_MSG, "LastLine = (%s)",(LPSTR)(&(pTG->FComModem.bLastReply)));
  282. uRespLen = min(cbMaxOut, _fstrlen(pTG->FComModem.bLastReply));
  283. _fmemcpy(lpbRespOut, pTG->FComModem.bLastReply, uRespLen);
  284. lpbRespOut[uRespLen] = 0; // zero terminate the string
  285. return uRespLen;
  286. }
  287. USHORT GetIdForClass
  288. (
  289. PThrdGlbl pTG,
  290. NPGETIDSTRUCT npgids,
  291. LPBYTE lpbOut,
  292. USHORT cbMaxOut,
  293. LPBYTE lpbLongestId,
  294. USHORT cbMaxLongestId,
  295. LPBYTE lpbLongestCmd
  296. )
  297. /*++
  298. Routine Description:
  299. The functions returns a id string for the modem.
  300. The string is class dependent (as indicated in npgids,uGoClass).
  301. The string will be in the format id1;id2;..idn where id<i> is the response of the
  302. modem to command i in the input GETIDSTRUCT::CmdTable array.
  303. It optionally returns the longest id ( form the result of the first 3 commands) and
  304. the command that generatedthis longest id.
  305. Arguments:
  306. pTG [IN/OU]
  307. A pointer to the infamous ThrdGlbl.
  308. npgids [IN]
  309. Pointer to GETIDSTRUCT that specifies the commands to send to get the id
  310. lpbOut [OUT]
  311. A buffer where the generated id string will be placed.
  312. The string will be in the format id1;id2;..idn where id<i> is the response of the
  313. modem to command i in the input GETIDSTRUCT::CmdTable array.
  314. cbMaxOut [IN]
  315. The maximum size of the above buffer
  316. lpbLongestId [OUT] OPTIONAL
  317. A buffer where longest id string will be placed.
  318. Can be NULL in which case it will not be used.
  319. cbMaxLongestId [IN] OPTIONAL
  320. The size of the longest id buffer
  321. lpbLongestCmd
  322. A pointer to the command string (in the provided npgids::CmdTable) that generated
  323. the longer id as described above.
  324. Return Value:
  325. --*/
  326. {
  327. USHORT i, j, k, uRet, uLen, uLenLong, iLong;
  328. LPBYTE lpbLong;
  329. DEBUG_FUNCTION_NAME(TEXT("GetIdForClass"));
  330. cbMaxOut -= 2; // make space for trailing ; and \0
  331. if(lpbLongestId)
  332. cbMaxLongestId -= 1; // make space for trailing \0
  333. uLen=0;
  334. if(npgids->uGoClass)
  335. {
  336. //@
  337. //@ Put the modem into the class required to use the id commands
  338. //@
  339. DebugPrintEx(DEBUG_MSG,
  340. TEXT("Putting the modem into class %ld"),
  341. npgids->uGoClass);
  342. if(!iiModemGoClass(pTG, npgids->uGoClass, 0))
  343. {
  344. DebugPrintEx( DEBUG_ERR,
  345. "GoClass %d failed",
  346. npgids->uGoClass);
  347. goto done;
  348. }
  349. }
  350. for(lpbLong=NULL, uLenLong=0, i=0; i<npgids->uNum; i++)
  351. {
  352. //@
  353. //@ Sent the command at index I in the command table to the modem
  354. //@ and get the response in (*lpbOut+uLen). This effectively
  355. //@ concatenates all the responses (seperated with ";")
  356. //@
  357. uRet = GetIdResp(
  358. pTG,
  359. npgids->CmdTable[i],
  360. npgids->uLen,
  361. lpbOut+uLen,
  362. (USHORT)(cbMaxOut-uLen)
  363. );
  364. // find longest ID among ATI0 thru 3 only!
  365. if(i<=3 && uLenLong < cbMaxLongestId && uRet > uLenLong)
  366. {
  367. //@
  368. //@ Update the length of the longest id (but not above the
  369. //@ max size the caller specified).
  370. //@
  371. uLenLong = min(uRet, cbMaxLongestId);
  372. //@
  373. //@ lpbLong points to the longets id
  374. //@
  375. lpbLong = lpbOut + uLen;
  376. //@
  377. //@ iLong id holds the index (0,1,2) of the longer id
  378. //@
  379. iLong = i;
  380. }
  381. uLen += uRet;
  382. //@
  383. //@ Seperate the ids by a ";"
  384. //@
  385. lpbOut[uLen++] = ';';
  386. }
  387. lpbOut[uLen] = 0;
  388. if(lpbLongestId && lpbLongestCmd && cbMaxLongestId && lpbLong && uLenLong)
  389. {
  390. //@
  391. //@ Copy the longest id (0,1 or 2) to the caller's buffer
  392. //@
  393. _fmemcpy(lpbLongestId, lpbLong, uLenLong);
  394. lpbLongestId[uLenLong] = 0;
  395. //@
  396. //@ Copy the command that generated the longest id to the caller's buffer
  397. //@
  398. _fmemcpy(lpbLongestCmd, npgids->CmdTable[iLong], npgids->uLen);
  399. lpbLongestCmd[npgids->uLen] = 0;
  400. DebugPrintEx( DEBUG_MSG,
  401. "LongestId (%s)-->(%s)",
  402. (LPSTR)lpbLongestCmd,
  403. (LPSTR)lpbLongestId);
  404. }
  405. // strip non-prinatbles. *AFTER* extracting the ModemId string!!
  406. for(j=0, k=0; j<uLen; j++)
  407. {
  408. if(lpbOut[j] >= 32 && lpbOut[j] <= 127)
  409. lpbOut[k++] = lpbOut[j];
  410. }
  411. uLen = k;
  412. lpbOut[uLen] = 0;
  413. DebugPrintEx( DEBUG_MSG,
  414. "Class%dId (%s)",
  415. npgids->uGoClass,
  416. (LPSTR)lpbOut);
  417. done:
  418. if(npgids->uGoClass)
  419. {
  420. //@
  421. //@ Go back to class 0 if we changes classes
  422. //@
  423. iiModemGoClass(pTG, 0, 0);
  424. }
  425. return uLen;
  426. }
  427. void iModemGetWriteIds(PThrdGlbl pTG, BOOL fGotOEMInfo)
  428. {
  429. // As with iModemFigureOutCmds and iModemGetCaps, we selectively
  430. // detect ID's taking into account OEM info that's already read in...
  431. USHORT uLen1, uLen2, uLen3;
  432. DWORD_PTR dwKey=0;
  433. LPSTR lpstr1 = 0, lpstr2 = 0, lpstr3 = 0;
  434. USHORT uClasses = pTG->TmpSettings.lpMdmCaps->uClasses;
  435. DEBUG_FUNCTION_NAME(("iModemGetWriteIds"));
  436. uLen1 = uLen2 = uLen3 = 0;
  437. //@ Open the device key
  438. if (!(dwKey=ProfileOpen( pTG->FComModem.dwProfileID,
  439. pTG->FComModem.rgchKey,
  440. fREG_CREATE | fREG_READ | fREG_WRITE)))
  441. {
  442. DebugPrintEx(DEBUG_ERR,"Couldn't get location of modem info.");
  443. goto end;
  444. }
  445. if (pTG->TmpSettings.dwGot & fGOTPARM_IDCMD)
  446. {
  447. //@
  448. //@ We already have the id command (we read it from the registry during iModemGetCurrentModemInfo)
  449. //@
  450. int i=0;
  451. if (!pTG->TmpSettings.szIDCmd[0])
  452. {
  453. //@
  454. //@ We have a null ID command so we can't really do anything
  455. //@ just save and exit.
  456. goto SaveIDandCMD;
  457. }
  458. //@
  459. //@ We have a non empty id command and can try to use it to detect the id.
  460. //@
  461. while(i++<2)
  462. {
  463. pTG->TmpSettings.szID[0]=0;
  464. pTG->TmpSettings.szResponseBuf[0]=0;
  465. //@ Send the id command to the modem. The id string is returned
  466. //@ in pTG->TmpSettigns.szID
  467. GetIdResp( pTG,
  468. pTG->TmpSettings.szIDCmd,
  469. (USHORT) _fstrlen(pTG->TmpSettings.szIDCmd),
  470. pTG->TmpSettings.szID,
  471. MAXIDSIZE);
  472. //@
  473. //@ Send the id command again this time putting the result
  474. //@ in pTG->TmpSettings.szResponseBuf.
  475. //@
  476. GetIdResp( pTG,
  477. pTG->TmpSettings.szIDCmd,
  478. (USHORT)_fstrlen(pTG->TmpSettings.szIDCmd),
  479. pTG->TmpSettings.szResponseBuf,
  480. MAXIDSIZE);
  481. //@
  482. //@ Compate the two results. If they are the same then break.
  483. //@ Otherwise try again.
  484. //@ (Why do we need to do this comparision ????)
  485. //@
  486. if (!_fstrcmp(pTG->TmpSettings.szID, pTG->TmpSettings.szResponseBuf))
  487. {
  488. break;
  489. }
  490. }
  491. if (i>=3 || !pTG->TmpSettings.szID[0])
  492. {
  493. //@
  494. //@ We failed to the the id response.
  495. //@
  496. DebugPrintEx( DEBUG_ERR,
  497. "Can't get matching ID for supplied IDCMD: %s",
  498. (LPSTR) pTG->TmpSettings.szIDCmd);
  499. //@
  500. //@ Nullify the command id and id held in TmpSettings.
  501. //@
  502. pTG->TmpSettings.szIDCmd[0]=pTG->TmpSettings.szID[0]=0;
  503. }
  504. else
  505. {
  506. //@
  507. //@ The id command worked and we have a matching id.
  508. //@
  509. DebugPrintEx( DEBUG_MSG,
  510. "OEM IDCmd=%s --> %s",
  511. (LPSTR) pTG->TmpSettings.szIDCmd,
  512. (LPSTR) pTG->TmpSettings.szID);
  513. }
  514. //@
  515. //@ In any case we indicate that we have an id command and matchind id.
  516. //@ (Why do we do that in the case we did not find a matching id ?)
  517. //@ And save the results to the registry.
  518. pTG->TmpSettings.dwGot |= (fGOTPARM_IDCMD | fGOTPARM_ID);
  519. goto SaveIDandCMD;
  520. }
  521. //@
  522. //@ This is the case where we do not have a command id that we previously found.
  523. //@
  524. // write ModemId first, then ModemIdCmd
  525. // the lpszOemIDCmd and lpszOemID above).
  526. pTG->TmpSettings.szID[0]=0;
  527. lpstr1 = pTG->TmpSettings.szResponseBuf;
  528. //@
  529. //@ Get the class 0 full id string into lpstr1.
  530. //@ Get the longest id (1st three commands) into pTG->TmpSettings.szID
  531. //@ Get the command that generated the longest id into pTG->TmpSettings.szIDCmd
  532. //@
  533. uLen1 = GetIdForClass(pTG, &GetIdTable[0], lpstr1,
  534. RESPONSEBUFSIZE, pTG->TmpSettings.szID, MAXIDSIZE,
  535. pTG->TmpSettings.szIDCmd);
  536. lpstr1[uLen1] = 0;
  537. if (pTG->TmpSettings.szID[0])
  538. {
  539. pTG->TmpSettings.dwGot |= (fGOTPARM_IDCMD|fGOTPARM_ID);
  540. }
  541. //@
  542. //@ Write the full id string for class 0 into the registry (Class0ModemId)
  543. //@
  544. ProfileWriteString(dwKey, GetIdTable[0].szIniEntry, lpstr1, FALSE);
  545. if(uClasses & FAXCLASS2) //@ if the modem supports class 2
  546. {
  547. //@
  548. //@ Get the class 2 full id string into lpstr2.
  549. //@ Dont ask for longest id (not relevant for class 2).
  550. //@ Note that lptstr2 is placed just after lpstr1 in pTG->TmpSettings.szResponseBuf
  551. //@
  552. lpstr2 = pTG->TmpSettings.szResponseBuf + uLen1 + 1;
  553. uLen2 = GetIdForClass(pTG, &GetIdTable[1], lpstr2,
  554. (USHORT)(RESPONSEBUFSIZE-uLen1-1), 0, 0, 0);
  555. lpstr2[uLen2] = 0;
  556. ProfileWriteString(dwKey, GetIdTable[1].szIniEntry, lpstr2, FALSE);
  557. }
  558. if(uClasses & FAXCLASS2_0) //@ if the modem supports class 2.0
  559. {
  560. lpstr3 = pTG->TmpSettings.szResponseBuf + uLen1 + uLen2 + 2;
  561. //@
  562. //@ Get the class 2.0 full id string into lpstr3.
  563. //@ Dont ask for longest id (not relevant for class 2).
  564. //@ Note that lptstr3 is placed just after lpstr2 in pTG->TmpSettings.szResponseBuf
  565. //@
  566. uLen3 = GetIdForClass(pTG, &GetIdTable[2], lpstr3, (USHORT)((RESPONSEBUFSIZE)-uLen1-uLen2-2), 0, 0, 0);
  567. lpstr3[uLen3] = 0;
  568. ProfileWriteString(dwKey, GetIdTable[2].szIniEntry, lpstr3, FALSE);
  569. }
  570. //@
  571. //@ Note: At this point we changed the value of pTG->TmpSettings.szId and szIdCmd.
  572. //@ and placed there the class 0 id and command respectively.
  573. //@
  574. ToCaps(lpstr1);
  575. ToCaps(lpstr2);
  576. ToCaps(lpstr3);
  577. DebugPrintEx( DEBUG_MSG,
  578. "Got Ids (%s)\r\n(%s)\r\n(%s)",
  579. ((LPSTR)(lpstr1 ? lpstr1 : "null")),
  580. ((LPSTR)(lpstr2 ? lpstr2 : "null")),
  581. ((LPSTR)(lpstr3 ? lpstr3 : "null")));
  582. // If we've read any commands or caps from the OEM location we
  583. // skip this...
  584. //@
  585. //@ This means that if we read the information from Unimodem key
  586. //@ or find it in the adaptive answering file we will never search
  587. //@ AWMODEM.INF or AWOEM.INF
  588. //@
  589. if (fGotOEMInfo || ( pTG->ModemKeyCreationId != MODEMKEY_FROM_NOTHING) )
  590. {
  591. DebugPrintEx(DEBUG_WRN,"Got OEM info: Skipping AWMODEM.INF file search!");
  592. }
  593. else
  594. {
  595. if (!SearchInfFile(pTG, "AWOEM.INF", lpstr1, lpstr2, lpstr3, dwKey))
  596. {
  597. SearchInfFile(pTG, "AWMODEM.INF", lpstr1, lpstr2, lpstr3, dwKey);
  598. }
  599. }
  600. SaveIDandCMD:
  601. ProfileWriteString(dwKey, szModemId, pTG->TmpSettings.szID, FALSE);
  602. ProfileWriteString(dwKey, szModemIdCmd, pTG->TmpSettings.szIDCmd, TRUE);
  603. end:
  604. if (dwKey) ProfileClose(dwKey);
  605. return;
  606. }
  607. // state: 0=ineol 1=insectionhdr 2=in midline 3=got] 4=got\r\n
  608. // inputs: \r\n==0 space/tab=1 2=[ 3=] 4=pritables 5=others
  609. USHORT uNext[5][6] =
  610. {
  611. // crlf sp [ ] asc oth
  612. { 0, 0, 1, 2, 2, 2 }, //in eol
  613. { 0, 1, 2, 3, 1, 2 }, //in sectionhdr
  614. { 0, 2, 2, 2, 2, 2 }, //in ordinary line
  615. { 4, 3, 2, 2, 2, 2 }, //found ]
  616. { 4, 4, 4, 4, 4, 4 } //found closing \r\n
  617. };
  618. #define START 0
  619. #define INHEADER1 1
  620. #define INHEADER2 3
  621. #define FOUND 4
  622. void ToCaps(LPBYTE lpb)
  623. {
  624. // capitalize string
  625. USHORT i;
  626. for(i=0; lpb && lpb[i]; i++)
  627. {
  628. if(lpb[i] >= 'a' && lpb[i] <= 'z')
  629. lpb[i] -= 32;
  630. }
  631. }
  632. BOOL SearchInfFile
  633. (
  634. PThrdGlbl pTG,
  635. LPSTR lpstrFile,
  636. LPSTR lpstr1,
  637. LPSTR lpstr2,
  638. LPSTR lpstr3,
  639. DWORD_PTR dwLocalKey
  640. )
  641. {
  642. char bTemp[BIGTEMPSIZE];
  643. char szHeader[SMALLTEMPSIZE+SMALLTEMPSIZE];
  644. char bTemp2[SMALLTEMPSIZE+SMALLTEMPSIZE];
  645. UINT uLen, state=0, input=0, uHdrLen;
  646. HFILE hfile;
  647. LPBYTE lpb, lpbCurr;
  648. DEBUG_FUNCTION_NAME(("SearchInfFile"));
  649. uLen = GetWindowsDirectory(bTemp, BIGTEMPSIZE-15);
  650. if(!uLen)
  651. {
  652. return FALSE;
  653. }
  654. // if last char is not a \ then append a '\'
  655. if(bTemp[uLen-1] != '\\')
  656. {
  657. bTemp[uLen++] = '\\';
  658. bTemp[uLen] = 0; // add new 0 terminator
  659. }
  660. _fstrcpy(bTemp+uLen, lpstrFile);
  661. if((hfile = DosOpen(bTemp, 0)) == HFILE_ERROR)
  662. {
  663. DebugPrintEx(DEBUG_WRN,"%s: No such file", (LPSTR)bTemp);
  664. return FALSE;
  665. }
  666. uLen = 0;
  667. lpbCurr = bTemp;
  668. nextround:
  669. DebugPrintEx(DEBUG_MSG,"Nextround");
  670. state = START;
  671. uHdrLen = 0;
  672. for(;;)
  673. {
  674. if(!uLen)
  675. {
  676. uLen = DosRead( hfile, bTemp, sizeof(bTemp));
  677. if(!uLen || uLen == ((UINT) -1))
  678. goto done;
  679. lpbCurr = bTemp;
  680. }
  681. switch(*lpbCurr)
  682. {
  683. case '\r':
  684. case '\n': input = 0; break;
  685. case ' ':
  686. case '\t': input = 1; break;
  687. case '[': input = 2; break;
  688. case ']': input = 3; break;
  689. default: if(*lpbCurr >= 32 && *lpbCurr < 128)
  690. {
  691. input = 4;
  692. }
  693. else
  694. {
  695. input = 5;
  696. }
  697. break;
  698. }
  699. state = uNext[state][input];
  700. if(state == FOUND)
  701. {
  702. if(uHdrLen > 2)
  703. {
  704. break;
  705. }
  706. else
  707. {
  708. goto nextround;
  709. }
  710. }
  711. if(state == INHEADER1)
  712. {
  713. if(*lpbCurr != '[' && uHdrLen < sizeof(szHeader)-1)
  714. szHeader[uHdrLen++] = *lpbCurr;
  715. }
  716. else if(state != INHEADER2)
  717. uHdrLen=0;
  718. lpbCurr++;
  719. uLen--;
  720. // szHeader[uHdrLen] = 0;
  721. }
  722. DebugPrintEx(DEBUG_MSG,"Found[%s]", (LPSTR)szHeader);
  723. szHeader[uHdrLen] = 0;
  724. // capitalize search string
  725. ToCaps(szHeader);
  726. DebugPrintEx(DEBUG_MSG,"Found[%s]", (LPSTR)szHeader);
  727. if( (lpstr1 ? strstr(lpstr1, szHeader) : FALSE) ||
  728. (lpstr2 ? strstr(lpstr2, szHeader) : FALSE) ||
  729. (lpstr3 ? strstr(lpstr3, szHeader) : FALSE) )
  730. {
  731. DebugPrintEx( DEBUG_WRN,
  732. "Copying INI file section [%s] from %s",
  733. (LPSTR)szHeader,
  734. (LPSTR)lpstrFile);
  735. DosClose( hfile);
  736. // read the whole section as profile string
  737. if(GetPrivateProfileString(szHeader, NULL, "", bTemp, sizeof(bTemp), lpstrFile) == 0)
  738. {
  739. DebugPrintEx(DEBUG_ERR,"Can't read INF file section");
  740. return FALSE;
  741. }
  742. // copy it to our IniFile
  743. for(lpb=bTemp; *lpb; lpb += _fstrlen(lpb)+1)
  744. {
  745. // lpb is a key in the [szHeader] section of the INF file
  746. if(GetPrivateProfileString(szHeader, lpb, "", bTemp2, sizeof(bTemp2), lpstrFile) == 0)
  747. {
  748. DebugPrintEx(DEBUG_ERR,"Can't read INF file entry");
  749. }
  750. else
  751. {
  752. // copy it to our IniFile
  753. ProfileWriteString(dwLocalKey, lpb, bTemp2, FALSE);
  754. DebugPrintEx( DEBUG_MSG,
  755. "Wrote %s=%s",
  756. (LPSTR)lpb,
  757. (LPSTR)bTemp2);
  758. }
  759. }
  760. // found what we wanted. Outta here
  761. return TRUE;
  762. }
  763. // couldnt match, try again
  764. DebugPrintEx(DEBUG_MSG,"No match");
  765. goto nextround;
  766. done:
  767. DebugPrintEx(DEBUG_MSG,"End of INF file %s",(LPSTR)lpstrFile);
  768. // end of inf file--close it
  769. DosClose(hfile);
  770. return FALSE;
  771. }
  772. void CheckAwmodemInf(PThrdGlbl pTG)
  773. {
  774. USHORT uLen;
  775. char bTemp[BIGTEMPSIZE];
  776. HFILE hfile;
  777. DEBUG_FUNCTION_NAME(_T("CheckAwmodemInf"));
  778. uLen = (USHORT)GetWindowsDirectory(bTemp, sizeof(bTemp)-15);
  779. if(!uLen)
  780. {
  781. return;
  782. }
  783. // if last char is not a \ then append a '\'
  784. if(bTemp[uLen-1] != '\\')
  785. {
  786. bTemp[uLen++] = '\\';
  787. bTemp[uLen] = 0; // add new 0 terminator
  788. }
  789. _fstrcpy(bTemp+uLen, "AWMODEM.INF");
  790. if((hfile = DosCreate(bTemp, 0)) == HFILE_ERROR)
  791. {
  792. DebugPrintEx(DEBUG_ERR,"Could not create %s",(LPSTR)bTemp);
  793. }
  794. else
  795. {
  796. DosWrite( hfile, (LPSTR)szAwmodemInf, sizeof(szAwmodemInf)-1);
  797. DosClose( hfile);
  798. DebugPrintEx(DEBUG_WRN,"Created %s",(LPSTR)bTemp);
  799. }
  800. return;
  801. }
  802. #define ADDSTRING(DST, SRC) \
  803. u = _fstrlen(pTG->TmpSettings.SRC)+1; \
  804. _fmemcpy(pb, pTG->TmpSettings.SRC,u); \
  805. lpCmdTab->DST=pb;\
  806. pb+=u;
  807. USHORT iModemGetCmdTab
  808. (
  809. PThrdGlbl pTG,
  810. LPCMDTAB lpCmdTab,
  811. LPMODEMCAPS lpMdmCaps
  812. )
  813. {
  814. USHORT uRet = INIT_INTERNAL_ERROR;
  815. USHORT uPassCount = 0;
  816. BOOL fDontPurge=FALSE; //If true, we won't delete section in install.
  817. DEBUG_FUNCTION_NAME(("iModemGetCmdTab"));
  818. if (!imodem_alloc_tmp_strings(pTG))
  819. goto done;
  820. pTG->TmpSettings.lpMdmCaps = lpMdmCaps;
  821. ReadConfig:
  822. // check for ModemIdCmd, ModemId, ModemFaxClasses,
  823. // ResetCommand, SetupCommand, PreDialCommand, PreAnswerCommand,
  824. // ExitCommand, FaxSerialSpeed vars
  825. // and (if Class1) ModemSendCaps, ModemRecvCaps
  826. // if all present [some exceptions--see below], then verify that
  827. // ModemId is still correct (send ModemIdCmd, get ModemId)
  828. // if correct then copy all INI values into lpMdmCaps and lpCmdTab
  829. // else do full install
  830. // get ModemCaps from current settings
  831. imodem_clear_tmp_settings(pTG);
  832. if (!iModemGetCurrentModemInfo(pTG))
  833. {
  834. goto DoInstall;
  835. }
  836. SmashCapsAccordingToSettings(pTG);
  837. if (! pTG->fCommInitialized)
  838. {
  839. if( ! T30ComInit(pTG) )
  840. {
  841. DebugPrintEx(DEBUG_MSG,"T30ComInit failed");
  842. goto done;
  843. }
  844. FComDTR(pTG, TRUE); // Raise DTR in ModemInit
  845. FComFlush(pTG);
  846. pTG->fCommInitialized = 1;
  847. }
  848. // do modem reset, or ID check won't work (because of echo)
  849. if (!pTG->TmpSettings.szReset[0] && !pTG->TmpSettings.szResetGenerated[0])
  850. {
  851. DebugPrintEx(DEBUG_WRN,"NULL reset command specified!");
  852. }
  853. else
  854. {
  855. if(iModemReset(pTG, pTG->TmpSettings.szResetGenerated[0] ?
  856. pTG->TmpSettings.szResetGenerated :
  857. pTG->TmpSettings.szReset) < 0)
  858. {
  859. fDontPurge=TRUE; // we specifically don't purge in this case.
  860. goto DoInstall;
  861. }
  862. }
  863. uRet = 0;
  864. goto done;
  865. DoInstall:
  866. if(uPassCount > 0)
  867. {
  868. DebugPrintEx(DEBUG_ERR,"Install looping!!");
  869. uRet = INIT_INTERNAL_ERROR;
  870. goto done;
  871. }
  872. uPassCount++;
  873. // +++ currently we always do a "clean" install -- dwGot=0
  874. // EXCEPT that we use fDontPurge do determine whether we
  875. // delete the profile section or not.
  876. fDontPurge=fDontPurge|| (pTG->TmpSettings.uDontPurge!=0);
  877. imodem_clear_tmp_settings(pTG);
  878. if(uRet = iModemInstall(pTG, fDontPurge))
  879. {
  880. goto done; // failed
  881. }
  882. else
  883. {
  884. goto ReadConfig; // success
  885. }
  886. // on success we want to go back and start over because (a) we want to check
  887. // that everything is indeed OK and (b) UI etc may have modfied some of the
  888. // settings so we need to go back and read them in again.
  889. done:
  890. if (!uRet)
  891. {
  892. char *pb = pTG->bModemCmds;
  893. UINT u;
  894. // Initialize all command strings in lpCmdTab to static buffer,
  895. // copying from the corresponding strings in the TmpSettings structure.
  896. // the latter strings point into
  897. // the temporarily allocated buffer allocated in
  898. // imodem_alloc_tmp_strings and will be freed on exit.
  899. _fmemset(lpCmdTab, 0, sizeof(CMDTAB));
  900. if (pTG->TmpSettings.szResetGenerated[0])
  901. {
  902. ADDSTRING(szReset, szResetGenerated);
  903. }
  904. else
  905. {
  906. ADDSTRING(szReset, szReset);
  907. }
  908. if (pTG->TmpSettings.szSetupGenerated[0])
  909. {
  910. ADDSTRING(szSetup, szSetupGenerated);
  911. }
  912. else
  913. {
  914. ADDSTRING(szSetup, szSetup);
  915. }
  916. ADDSTRING(szExit, szExit);
  917. ADDSTRING(szPreDial, szPreDial);
  918. ADDSTRING(szPreAnswer, szPreAnswer);
  919. }
  920. lpCmdTab->dwSerialSpeed = pTG->SerialSpeedInit;
  921. lpCmdTab->dwFlags = pTG->TmpSettings.dwFlags;
  922. imodem_free_tmp_strings(pTG);
  923. return uRet;
  924. }
  925. USHORT iModemInstall
  926. (
  927. PThrdGlbl pTG,
  928. BOOL fDontPurge
  929. )
  930. {
  931. USHORT uRet = 0;
  932. BOOL fGotOEMInfo = FALSE;
  933. DWORD_PTR hkFr;
  934. DWORD localModemKeyCreationId;
  935. DEBUG_FUNCTION_NAME(("iModemInstall"));
  936. CheckAwmodemInf(pTG); // check that AWMODEM.INf exist, otherwise create it
  937. if (!pTG->TmpSettings.dwGot)
  938. {
  939. /////// clear settings in input //////
  940. // Clear out persistant (registry) info...
  941. if (!fDontPurge && !ProfileDeleteSection(DEF_BASEKEY,pTG->FComModem.rgchKey))
  942. {
  943. DebugPrintEx( DEBUG_WRN,
  944. "ClearCurrentModemInfo:Can't delete section %s",
  945. (LPSTR) pTG->FComModem.rgchKey);
  946. }
  947. {
  948. ULONG_PTR key;
  949. if (!(key=ProfileOpen(pTG->FComModem.dwProfileID, pTG->FComModem.rgchKey,
  950. fREG_CREATE | fREG_READ | fREG_WRITE)))
  951. {
  952. DebugPrintEx(DEBUG_ERR,"Couldn't get location of modem info.");
  953. }
  954. else
  955. {
  956. ProfileWriteString(key, szResetCommandGenerated, "", TRUE);
  957. ProfileWriteString(key, szSetupCommandGenerated, "", TRUE);
  958. ProfileClose(key);
  959. }
  960. }
  961. //@
  962. //@ First lets see if the modem has a Unimodem FAX key.
  963. //@ If it does then we will use the Unimodem FAX key settings
  964. //@ and will not attempt to search ADAPTIVE.INF AWMODEM.INF or AWOEM.INF
  965. //@ Note: This is different from thw W2K implementation. W2K provider
  966. //@ looked first in ADAPTIVE.INF and if it found a match it DID NOT
  967. //@ look for a Unimodem FAX key.
  968. //@
  969. pTG->ModemKeyCreationId = MODEMKEY_FROM_NOTHING;
  970. hkFr = ProfileOpen( OEM_BASEKEY, pTG->lpszUnimodemFaxKey, fREG_READ);
  971. if ( hkFr )
  972. {
  973. pTG->ModemKeyCreationId = MODEMKEY_FROM_UNIMODEM;
  974. ProfileClose( hkFr);
  975. //@
  976. //@ This copies all the information from the unimodem FAX key to
  977. //@ our registry.
  978. //@
  979. iModemCopyOEMInfo(pTG);
  980. }
  981. else
  982. {
  983. //@
  984. //@ Check to see if this modem is defined in Adaptive.Inf
  985. //@ Since the last parameret is FALSE we will not read in the record content
  986. //@ if it contains an "AdaptiveCodeId" field (which indiciates we need to
  987. //@ make sure what is the modem revision first). If it does not contain
  988. //@ this field we will read the content into the pTG.
  989. //@
  990. SearchNewInfFile(pTG, pTG->ResponsesKeyName, NULL, FALSE);
  991. if (pTG->fAdaptiveRecordFound)
  992. {
  993. if (! pTG->fAdaptiveRecordUnique)
  994. {
  995. //@
  996. //@ The section indicates that a modem id identification is required.
  997. //@ The next oddly named function will set pTG->fAdaptiveRecordUnique to 1
  998. //@ if it identified the modem revision as a one for which
  999. //@ adaptive answering is working.
  1000. //@
  1001. TalkToModem (pTG, FALSE); //@ void function
  1002. if (pTG->fAdaptiveRecordUnique)
  1003. {
  1004. //@
  1005. //@ Now we are we are sure the the adaptive record matches the modem.
  1006. //@ We search the INF again but this time allways read the record
  1007. //@ content into the pTG (last parameter is TRUE).
  1008. //@
  1009. SearchNewInfFile(pTG, pTG->ResponsesKeyName, NULL, TRUE);
  1010. }
  1011. else
  1012. {
  1013. //@
  1014. //@ The modem does not match the revision for which adaptive
  1015. //@ answering is enabled.
  1016. //@
  1017. pTG->fAdaptiveRecordFound = 0;
  1018. pTG->ModemClass = 0;
  1019. }
  1020. }
  1021. }
  1022. if (pTG->fAdaptiveRecordFound)
  1023. {
  1024. //@
  1025. //@ If we succeeded to find an adaptive record then we need
  1026. //@ to save the information we read from it into the pTG to the
  1027. //@ registry.
  1028. //@
  1029. pTG->ModemKeyCreationId = MODEMKEY_FROM_ADAPTIVE; //@ so we will know the information source
  1030. SaveInf2Registry(pTG);
  1031. }
  1032. }
  1033. localModemKeyCreationId = pTG->ModemKeyCreationId;
  1034. pTG->AdaptiveAnswerEnable = 0; //@ we are going to read it back from the registry in a second
  1035. //
  1036. // At this point we have all the info from Adaptive.inf or Unimodem Reg.
  1037. // into Modem Reg.
  1038. // We have nothing in memory.
  1039. //
  1040. if (! pTG->ModemClass)
  1041. {
  1042. ReadModemClassFromRegistry(pTG);
  1043. }
  1044. if (! pTG->ModemClass)
  1045. {
  1046. TalkToModem(pTG, TRUE);
  1047. SaveModemClass2Registry(pTG);
  1048. }
  1049. //@
  1050. //@ Read the modem data back from the registry. (We have just written it
  1051. //@ to the registry in the preceeding functions and we want it back into
  1052. //@ memory).
  1053. //@ Note that this sets pTG->TmpSettings.dwGot with the fGOTCAPS_X, fGOTPARM_X, etc. flags
  1054. //@ Also note that this will turn off or on the adaptive answering flag
  1055. //@ (pTG->AdaptiveAnswerEnable) based on the extension configuration of the T30 FSP.
  1056. //@
  1057. iModemGetCurrentModemInfo(pTG);
  1058. pTG->ModemKeyCreationId = localModemKeyCreationId;
  1059. }
  1060. //
  1061. // We are ready now to initialize the hardware.
  1062. // Can be second init (first one is in TalkToModem
  1063. //
  1064. if(! T30ComInit(pTG) )
  1065. {
  1066. DebugPrintEx(DEBUG_ERR,"Cannot Init COM port");
  1067. // error already set to ERR_COMM_FAILED
  1068. uRet = INIT_PORTBUSY;
  1069. goto done;
  1070. }
  1071. FComDTR(pTG, TRUE); // Raise DTR in ModemInit
  1072. FComFlush(pTG);
  1073. pTG->fCommInitialized = 1;
  1074. // we use this to decide if we must read our OEM inf files or not....
  1075. //@ Make sure we have all what we need to operate. If we miss any of these
  1076. //@ we will attempt to find it in AWMODEM.INF and AWOEM.INF.
  1077. //@
  1078. //@ CMDS:
  1079. //@ fGOTCMD_Reset \
  1080. //@ fGOTCMD_Setup \
  1081. //@ fGOTCMD_PreAnswer \
  1082. //@ fGOTCMD_PreDial \
  1083. //@ fGOTCMD_PreExit
  1084. //@ CAPS:
  1085. //@ fGOTCAP_CLASSES
  1086. //@ fGOTCAP_SENDSPEEDS
  1087. //@ fGOTCAP_RECVSPEEDS
  1088. //@ PARAMS:
  1089. //@ fGOTPARM_PORTSPEED
  1090. //@ fGOTPARM_IDCMD
  1091. //@ fGOTPARM_ID
  1092. //@
  1093. fGotOEMInfo = (pTG->TmpSettings.dwGot & (fGOTCMDS|fGOTCAPS|fGOTPARMS));
  1094. // At this point, we have possibly an incompletely and/or
  1095. // incorrectly filled out set of commands and capabilities.
  1096. // must be first, or modem is in a totally unknown state
  1097. //@
  1098. //@ If the setup and reset command were not read or are not good
  1099. //@ iModemFigureOutCmdsExt attempts to find them and place them in
  1100. //@ pTG->TmpSettings.szReset and pTG->TmpSettings.szSetup
  1101. //@
  1102. if(uRet = iModemFigureOutCmdsExt(pTG))
  1103. goto done;
  1104. // iModemFigureOut leaves modem is a good (synced up) state
  1105. // this needs to be _after_ lpCmdTab is filled out
  1106. if(!iModemGetCaps( pTG,
  1107. pTG->TmpSettings.lpMdmCaps,
  1108. pTG->TmpSettings.dwSerialSpeed,
  1109. pTG->TmpSettings.szResetGenerated[0] ?
  1110. pTG->TmpSettings.szResetGenerated :
  1111. pTG->TmpSettings.szReset,
  1112. &pTG->TmpSettings.dwGot))
  1113. {
  1114. uRet = INIT_GETCAPS_FAIL;
  1115. goto done;
  1116. }
  1117. // we always save settings here because iModemGetWriteIds below
  1118. // will need to possibly override our settings so far...
  1119. iModemSaveCurrentModemInfo(pTG);
  1120. // must be last since it also does the AWMODEM.INF search
  1121. //@
  1122. //@ Note that iModemGetWriteIds will not do the INF search (and copy)
  1123. //@ if fGotOEMInfo is TRUE or if pTG->ModemKeyCreationId != MODEMKEY_FROM_NOTHING.
  1124. //@ This means that if we read the information from Unimodem the AWMODEM.INF and
  1125. //@ AWOEM.INF will be ignored. This is what we want !
  1126. //@
  1127. iModemGetWriteIds(pTG, fGotOEMInfo);
  1128. CleanModemInfStrings(pTG);
  1129. imodem_clear_tmp_settings(pTG);
  1130. // Now we've done all we can. We've got all the settings, written them to
  1131. // the INI file. Call back the UI function here. This will read the
  1132. // current settings from INI file, may modify them and returns OK, Cancel
  1133. // and Detect. On OK & Cancel, just exit. On Detect loop back to start
  1134. // of this function, but this time _skip_ UNIMODEM & do detection ourself
  1135. uRet = 0;
  1136. done:
  1137. return uRet;
  1138. }
  1139. /***-------------------- FLOW CONTROL ----------------------**********
  1140. Each modem seems to have it's own stupid way of setting
  1141. flow control. Here's a survey
  1142. Manuf which modem? Flow Sideeffects
  1143. ----- ------------ ---- -----------
  1144. Rockwell RC2324AC &K4 &H unused. \Q unused.
  1145. US Robotics Sportster14400 &H2 &K0-3 used, &K4 unused. \cmds unused
  1146. Courier(HST,V32bis)
  1147. PracPeriph PP14400FXMT/SA &K4 &H unsued. \cmds unused.
  1148. PP2400EFXSA
  1149. Zoom 9600 V.32 VFX &K4 &H unused. \Q unused
  1150. UDSMotorola Fastalk \Q1 &H unused &K unused
  1151. HayesOptima Optima24/144 &K4 &H unused \cmds unused
  1152. MegaHertz P2144 \Q1 \Q4 &H unused &K unused
  1153. TwinCom 144/DF &K4 &H unused \Q unused
  1154. PCLogic ??? ??? ????
  1155. ???? ??? \Q1 &H unused &K unused
  1156. ATI 2400 etc &K4 &H unused \cmds unused
  1157. MultiTech MultiModemMT1432MU &E5 &H unused &K unused \Q unused
  1158. MultiModemII MT932
  1159. MultiModemII MT224
  1160. Viva 14.4i/Fax and 9624i &K4 &H unused \Q unused &E unused
  1161. GVC "9600bps Fax Modem" \Q1 &H unused &K unused &E unused
  1162. SmartOne 1442F/1442FX &K4 &H unused \Q unused &E unused
  1163. DSI ScoutPlus *F2 &H &E &K \Q1 unused
  1164. We had &K4 and \Q1 commands being sent (until 7/10/93).
  1165. This is a potential problem for US Robotics, MultiTech
  1166. and DSI modems.
  1167. US Robotics defaults to ALL flow control disabled
  1168. DSI ScoutPlus defaults to CTS/RTS flow control
  1169. MultiTech defaults to CTS/RTS flow control
  1170. MultiTech is Class2-only, so we may not have trouble there
  1171. 7/10/93
  1172. Added &H2 command to iModemReInit -- doesn't affect anyone else I think
  1173. later
  1174. Removed &H2 -- some modems use that as 'help' cmd & display a page
  1175. of help info that they refuse to exit except on pressing N or some such!
  1176. So we think the modem's hung!
  1177. later
  1178. Removed *F2 -- Starts a Flassh ROM download on Rockwell!!
  1179. ****-------------------- FLOW CONTROL -------------------------*******/
  1180. /*************************************************************************
  1181. According to "Data and Fax Communications" by Hummel,flow control
  1182. settings are as follows
  1183. xon both
  1184. &H2 &H3 -- US Robotics (though this fatally invokes Help on some modems)
  1185. &K4 -- Dallas, Hayes, Practical, Prometheus, Rockwell, Sierra, Telebit
  1186. Twincom, Zoom
  1187. \Q1 -- AT&T, Dallas, Microcom, Practical, Prometheus, Sierra
  1188. *F2 -- Prometheus (though it fatally invokes Flash ROM download on Rockwell)
  1189. #K4 -- Sierra-based fax modems
  1190. S68=3 -- Telebit
  1191. **************************************************************************/
  1192. #define AT "AT"
  1193. #define ampF "&F"
  1194. #define S0_0 "S0=0"
  1195. #define E0 "E0"
  1196. #define V1 "V1"
  1197. #define Q0 "Q0"
  1198. #define S7_60 "S7=60"
  1199. #define ampD2 "&D2"
  1200. #define ampD3 "&D3"
  1201. #define bsQ1 "\\Q1"
  1202. #define bsJ0 "\\J0"
  1203. #define ampK4 "&K4"
  1204. #define ampH2 "&H2"
  1205. #define ampI2 "&I2"
  1206. #define ampE5 "&E5"
  1207. #define cr "\r"
  1208. //#define ampC1 "&C1"
  1209. USHORT iModemFigureOutCmdsExt(PThrdGlbl pTG)
  1210. /*++
  1211. Routine Description:
  1212. Tries to figure out the reset and setup command for the modem if the were
  1213. not read from the registry or what was read does not work.
  1214. If a reset command works the fGOTCMD_Reset is set in pTG->TmpSettings.dwGot and it is saved in pTG->TmpSettings.szReset.
  1215. If a setup command works the fGOTCMD_Setup is set in pTG->TmpSettings.dwGot and it is saved in pTG->TmpSettings.szReset.
  1216. if pTG->TmpSettings.dwSerialSpeed is not set (0) then we set it to pTG->SerialSpeedInit and turn on
  1217. the fGOTPARM_PORTSPEED flag.
  1218. Return Value:
  1219. 0 if succeeded.
  1220. INIT_MODEMDEAD if the modem does not respond.
  1221. --*/
  1222. {
  1223. USHORT uLen1 = 0, uLen2 = 0;
  1224. BOOL fGotFlo;
  1225. // At this point, we have possibly an incompletely and/or
  1226. // incorrectly filled out set of commands and capabilities.
  1227. // Our job here is to use a combination of detection and
  1228. // pre-filled commands to come up with a working set of
  1229. // commands..
  1230. DEBUG_FUNCTION_NAME(_T("iModemFigureOutCmdsExt"));
  1231. if (pTG->TmpSettings.dwGot & fGOTCMD_Reset)
  1232. {
  1233. //@
  1234. //@ If we read a reset command from the registry we
  1235. //@ don't attempt to find it if it is NULL or empty.
  1236. if (!(pTG->TmpSettings.szReset)
  1237. || !*(pTG->TmpSettings.szReset)
  1238. || iModemReset(pTG, pTG->TmpSettings.szReset) >= 0)
  1239. {
  1240. //@ If we dont have a pre read reset command
  1241. //@ or the reset command is empty
  1242. //@ or we succeeded in getting a response from the specified reset command
  1243. //@ then we don't attemp to figure this out.
  1244. goto SkipReset;
  1245. }
  1246. else
  1247. {
  1248. DebugPrintEx( DEBUG_WRN,
  1249. "BOGUS supplied reset cmd: \"%s\"",
  1250. (LPSTR) pTG->TmpSettings.szReset);
  1251. }
  1252. }
  1253. //@
  1254. //@ We wither did not read a reset command from the registr or read
  1255. //@ a non empty one and it did not work.
  1256. //@
  1257. //@ We now try to figure out the right reset command by just trying
  1258. //@ the most common strings...
  1259. //@
  1260. // Quick test to see if we have a modem at all...
  1261. // +++ REMOVE!
  1262. _fstrcpy(pTG->TmpSettings.szSmallTemp1, AT E0 V1 cr);
  1263. if(iModemReset(pTG, pTG->TmpSettings.szSmallTemp1) < 0)
  1264. {
  1265. DebugPrintEx(DEBUG_ERR,"can't set ATE0V1");
  1266. goto modem_dead;
  1267. }
  1268. _fstrcpy(pTG->TmpSettings.szSmallTemp1, AT ampF S0_0 E0 V1 Q0 cr);
  1269. if(iModemReset(pTG, pTG->TmpSettings.szSmallTemp1) >= 0)
  1270. goto GotReset;
  1271. // too many variants, too slow, V1Q0 are default anyway
  1272. //_fstrcpy(pTG->TmpSettings.szSmallTemp1, AT ampF S0_0 E0 V1 cr);
  1273. //if(iModemReset(pTG->TmpSettings.szSmallTemp1) >= 0)
  1274. // goto GotReset;
  1275. _fstrcpy(pTG->TmpSettings.szSmallTemp1, AT ampF S0_0 E0 cr);
  1276. if(iModemReset(pTG, pTG->TmpSettings.szSmallTemp1) >= 0)
  1277. goto GotReset;
  1278. _fstrcpy(pTG->TmpSettings.szSmallTemp1, AT ampF E0 cr);
  1279. if(iModemReset(pTG, pTG->TmpSettings.szSmallTemp1) >= 0)
  1280. goto GotReset;
  1281. DebugPrintEx(DEBUG_ERR,"can't set AT&FE0");
  1282. // Purge comm here, because there may be stuff left in the output
  1283. // buffer that FComClose will try to complete, and if the modem
  1284. // is dead, that will take a while...
  1285. modem_dead:
  1286. FComFlush(pTG);
  1287. return INIT_MODEMDEAD;
  1288. GotReset:
  1289. //@
  1290. //@ We succeeded in figuring out a reset command. Turn on the fGOTCMD_Reset flag
  1291. //@ and save it in pTG->TmpSettings.szReset.
  1292. //@
  1293. pTG->TmpSettings.dwGot |= fGOTCMD_Reset;
  1294. _fstrcpy(pTG->TmpSettings.szResetGenerated, pTG->TmpSettings.szSmallTemp1);
  1295. SkipReset:
  1296. // now try setup cmd
  1297. if (pTG->TmpSettings.dwGot & fGOTCMD_Setup)
  1298. {
  1299. if (!(pTG->TmpSettings.szSetup)
  1300. || !*(pTG->TmpSettings.szSetup)
  1301. || OfflineDialog2(pTG, pTG->TmpSettings.szSetup,
  1302. (USHORT)_fstrlen(pTG->TmpSettings.szSetup), cbszOK,
  1303. cbszERROR)==1)
  1304. {
  1305. goto SkipSetup;
  1306. }
  1307. else
  1308. {
  1309. DebugPrintEx( DEBUG_WRN,
  1310. "BOGUS supplied setup cmd: \"%s\"\r\n",
  1311. (LPSTR) pTG->TmpSettings.szSetup);
  1312. }
  1313. }
  1314. _fstrcpy(pTG->TmpSettings.szSmallTemp1, AT);
  1315. uLen2 = sizeof(AT)-1;
  1316. if(OfflineDialog2(pTG, (LPSTR)(AT S7_60 cr), sizeof(AT S7_60 cr)-1, cbszOK, cbszERROR) == 1)
  1317. {
  1318. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, S7_60);
  1319. uLen2 += sizeof(S7_60)-1;
  1320. }
  1321. else
  1322. {
  1323. DebugPrintEx(DEBUG_WRN,"can't set S7=255");
  1324. }
  1325. if(OfflineDialog2(pTG, (LPSTR)(AT ampD3 cr), sizeof(AT ampD3 cr)-1, cbszOK, cbszERROR) == 1)
  1326. {
  1327. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, ampD3);
  1328. uLen2 += sizeof(ampD3)-1;
  1329. }
  1330. else if(OfflineDialog2(pTG, (LPSTR)(AT ampD2 cr), sizeof(AT ampD2 cr)-1, cbszOK, cbszERROR) == 1)
  1331. {
  1332. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, ampD2);
  1333. uLen2 += sizeof(ampD2)-1;
  1334. }
  1335. else
  1336. {
  1337. DebugPrintEx(DEBUG_WRN,"can't set &D3 or &D2");
  1338. }
  1339. fGotFlo=FALSE;
  1340. if(OfflineDialog2(pTG, (LPSTR)(AT ampK4 cr), sizeof(AT ampK4 cr)-1, cbszOK, cbszERROR) == 1)
  1341. {
  1342. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, ampK4);
  1343. uLen2 += sizeof(ampK4)-1;
  1344. fGotFlo=TRUE;
  1345. }
  1346. // JosephJ 3/10/95: We try \Q1\J0 even if &K4 passed,
  1347. // because many japanese modems return OK to &K4 but in fact
  1348. // use \J0 for xon xoff flow control
  1349. if(OfflineDialog2(pTG, (LPSTR)(AT bsQ1 cr), sizeof(AT bsQ1 cr)-1, cbszOK, cbszERROR) == 1)
  1350. {
  1351. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, bsQ1);
  1352. uLen2 += sizeof(bsQ1)-1;
  1353. if(OfflineDialog2(pTG, (LPSTR)(AT bsJ0 cr), sizeof(AT bsJ0 cr)-1, cbszOK, cbszERROR) == 1)
  1354. {
  1355. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, bsJ0);
  1356. uLen2 += sizeof(bsJ0)-1;
  1357. }
  1358. fGotFlo=TRUE;
  1359. }
  1360. if (!fGotFlo)
  1361. {
  1362. DebugPrintEx(DEBUG_WRN,"can't set &K4 or \\Q1, trying &K5");
  1363. if(OfflineDialog2(pTG, (LPSTR)(AT ampE5 cr), sizeof(AT ampE5 cr)-1, cbszOK, cbszERROR) == 1)
  1364. {
  1365. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, ampE5);
  1366. uLen2 += sizeof(ampE5)-1;
  1367. fGotFlo=TRUE;
  1368. }
  1369. }
  1370. _fstrcpy(pTG->TmpSettings.szSmallTemp1+uLen2, cr);
  1371. uLen2 += sizeof(cr)-1;
  1372. _fstrcpy(pTG->TmpSettings.szSetupGenerated, pTG->TmpSettings.szSmallTemp1);
  1373. pTG->TmpSettings.dwGot |=fGOTCMD_Setup;
  1374. SkipSetup:
  1375. if (!pTG->TmpSettings.dwSerialSpeed)
  1376. {
  1377. pTG->TmpSettings.dwSerialSpeed = pTG->SerialSpeedInit;
  1378. pTG->TmpSettings.dwGot |=fGOTPARM_PORTSPEED;
  1379. }
  1380. return 0;
  1381. }
  1382. void
  1383. TalkToModem
  1384. (
  1385. PThrdGlbl pTG,
  1386. BOOL fGetClass
  1387. )
  1388. {
  1389. char Command [400];
  1390. char Response[1000];
  1391. DWORD RespLen;
  1392. USHORT uRet;
  1393. char *lpBeg;
  1394. char *lpCur;
  1395. #define uMULTILINE_SAVEENTIRE 0x1234
  1396. //
  1397. // This function implements special case modems firmware identification
  1398. // as well as modem class identification.
  1399. //
  1400. DEBUG_FUNCTION_NAME(("TalkToModem"));
  1401. if ( (! fGetClass) && (pTG->AdaptiveCodeId != 1) )
  1402. {
  1403. return;
  1404. }
  1405. //
  1406. // Initialize modem
  1407. //
  1408. if(! T30ComInit(pTG) )
  1409. {
  1410. DebugPrintEx(DEBUG_ERR,"cannot init COM port");
  1411. return;
  1412. }
  1413. FComDTR(pTG, TRUE); // Raise DTR in ModemInit
  1414. FComFlush(pTG);
  1415. pTG->fCommInitialized = 1;
  1416. sprintf (Command, "AT E0 Q0 V1\r" );
  1417. if( (uRet = OfflineDialog2(pTG, (LPSTR) Command, (USHORT) strlen(Command), cbszOK, cbszERROR) ) != 1)
  1418. {
  1419. DebugPrintEx(DEBUG_ERR, "1 %s FAILED", Command);
  1420. return;
  1421. }
  1422. DebugPrintEx(DEBUG_MSG,"TalkToModem 1 %s rets OK", Command);
  1423. if (fGetClass)
  1424. {
  1425. //
  1426. // Get modem class
  1427. //
  1428. pTG->ModemClass=MODEM_CLASS1; // default
  1429. sprintf (Command, "AT+FCLASS=?\r" );
  1430. if( (uRet = OfflineDialog2(pTG, (LPSTR) Command, (USHORT) strlen(Command), cbszOK, cbszERROR) ) != 1)
  1431. {
  1432. DebugPrintEx(DEBUG_ERR, "TalkToModem 1 %s FAILED", Command);
  1433. return;
  1434. }
  1435. DebugPrintEx( DEBUG_MSG,
  1436. "TalkToModem 1 %s returned %s",
  1437. Command,
  1438. pTG->FComModem.bLastReply);
  1439. if (strchr(pTG->FComModem.bLastReply, '1') )
  1440. {
  1441. DebugPrintEx(DEBUG_MSG, "Default to Class1");
  1442. }
  1443. else if ( lpBeg = strchr (pTG->FComModem.bLastReply, '2') )
  1444. {
  1445. lpBeg++;
  1446. if ( *lpBeg != '.' )
  1447. {
  1448. DebugPrintEx(DEBUG_MSG, "Default to Class2");
  1449. pTG->ModemClass=MODEM_CLASS2;
  1450. }
  1451. else if ( strchr (lpBeg, '2') )
  1452. {
  1453. DebugPrintEx(DEBUG_MSG, "Default to Class2");
  1454. pTG->ModemClass=MODEM_CLASS2;
  1455. }
  1456. else
  1457. {
  1458. DebugPrintEx(DEBUG_MSG, "Default to Class2.0");
  1459. pTG->ModemClass=MODEM_CLASS2_0;
  1460. }
  1461. }
  1462. else
  1463. {
  1464. DebugPrintEx(DEBUG_ERR, "Could not get valid Class answer. Default to Class1");
  1465. }
  1466. }
  1467. //
  1468. // If needed, get firmware identification.
  1469. //
  1470. switch (pTG->AdaptiveCodeId)
  1471. {
  1472. case 1:
  1473. // Sportster 28800-33600 internal/external
  1474. sprintf (Command, "ATI7\r" );
  1475. FComFlushOutput(pTG);
  1476. FComDirectAsyncWrite(pTG, (LPSTR) Command, (USHORT) strlen(Command) );
  1477. if ( ( uRet = iiModemDialog( pTG, 0, 0, 5000, uMULTILINE_SAVEENTIRE,1, TRUE,
  1478. cbszOK,
  1479. cbszERROR,
  1480. (CBPSTR)NULL) ) != 1 )
  1481. {
  1482. DebugPrintEx(DEBUG_ERR, "TalkToModem 2 %s FAILED", Command);
  1483. return;
  1484. }
  1485. DebugPrintEx(DEBUG_MSG,"TalkToModem 2 %s rets OK", Command);
  1486. RespLen = min(sizeof(Response) - 1, strlen(pTG->FComModem.bEntireReply) );
  1487. memcpy(Response, pTG->FComModem.bEntireReply, RespLen);
  1488. Response[RespLen] = 0;
  1489. ToCaps(Response);
  1490. //
  1491. // if "EPROM DATE" is "10/18/95" then the adaptive answer is broken (Hugh Riley, USR 03/25/97).
  1492. // otherwise enable adaptive answer.
  1493. // If we enabled adaptive answer and firmware is broken then the customer needs to upgrade f/w.
  1494. //
  1495. if ( ! strstr(Response, "10/18/95") )
  1496. {
  1497. pTG->fAdaptiveRecordUnique = 1;
  1498. return;
  1499. }
  1500. //
  1501. // found "10/18/95". Lets check if this is an EPROM DATE.
  1502. //
  1503. if ( ! (lpBeg = strstr(Response, "EPROM DATE") ) )
  1504. {
  1505. return;
  1506. }
  1507. if ( ! (lpCur = strstr(lpBeg, "10/18/95") ) )
  1508. {
  1509. pTG->fAdaptiveRecordUnique = 1;
  1510. return;
  1511. }
  1512. if ( ! strstr(lpCur, "DSP DATE") )
  1513. {
  1514. pTG->fAdaptiveRecordUnique = 1;
  1515. return;
  1516. }
  1517. return;
  1518. default:
  1519. return;
  1520. }
  1521. return;
  1522. }
  1523. BOOL iModemGetCurrentModemInfo(PThrdGlbl pTG)
  1524. // Reads as much as it can from the current profile. Returns TRUE
  1525. // IFF it has read enough for a proper init.
  1526. // On failure, zero's out everything.
  1527. // All info is maintained in global TmpSettings;
  1528. {
  1529. USHORT uLen1 = 0;
  1530. USHORT uLen2 = 0;
  1531. ULONG_PTR dwKey = 0;
  1532. ULONG_PTR dwKeyAdaptiveAnswer = 0;
  1533. ULONG_PTR dwKeyAnswer = 0;
  1534. ULONG_PTR UnimodemFaxKey = 0;
  1535. BOOL fRet = FALSE;
  1536. ULONG_PTR KeyList[10] = {0};
  1537. char KeyName[200] = {0};
  1538. char lpTemp[MAXCMDSIZE] = {0};
  1539. char szClass[10] = {0};
  1540. DWORD i = 0;
  1541. UINT uTmp = 0;
  1542. LPMODEMCAPS lpMdmCaps = pTG->TmpSettings.lpMdmCaps;
  1543. DEBUG_FUNCTION_NAME(("iModemGetCurrentModemInfo"));
  1544. imodem_clear_tmp_settings(pTG);
  1545. //
  1546. // get T.30 modem Fax key
  1547. //
  1548. if ( ! (dwKey = ProfileOpen(pTG->FComModem.dwProfileID, pTG->FComModem.rgchKey, fREG_READ)))
  1549. {
  1550. goto end;
  1551. }
  1552. // open the Unimodem fax section
  1553. UnimodemFaxKey = ProfileOpen(OEM_BASEKEY,pTG->lpszUnimodemFaxKey,fREG_READ);
  1554. if (!UnimodemFaxKey)
  1555. {
  1556. // Fax section in Unimodem's registry does not exist.
  1557. // There's no need to worry if Windows Update was used
  1558. // to change settings there. Our cache is correct.
  1559. DebugPrintEx(DEBUG_MSG, "Modem does not have a Fax section in its INF");
  1560. }
  1561. //
  1562. // Lets see what modem Class we will use
  1563. //
  1564. uTmp = ProfileGetInt(dwKey, szFixModemClass, 0, FALSE);
  1565. if (IsCacheIntDirty(UnimodemFaxKey,szFixModemClass,uTmp))
  1566. {
  1567. DebugPrintEx(DEBUG_WRN, "FixModemClass cached settings are invalid, need to re-install the modem.");
  1568. fRet = FALSE;
  1569. goto end;
  1570. }
  1571. if (uTmp == 1)
  1572. {
  1573. pTG->ModemClass = MODEM_CLASS1;
  1574. }
  1575. else if (uTmp == 2)
  1576. {
  1577. pTG->ModemClass = MODEM_CLASS2;
  1578. }
  1579. else if (uTmp == 20)
  1580. {
  1581. pTG->ModemClass = MODEM_CLASS2_0;
  1582. }
  1583. if (! pTG->ModemClass)
  1584. {
  1585. DebugPrintEx(DEBUG_ERR, "MODEM CLASS was not defined.");
  1586. }
  1587. switch (pTG->ModemClass)
  1588. {
  1589. case MODEM_CLASS1 :
  1590. sprintf(szClass, "Class1");
  1591. break;
  1592. case MODEM_CLASS2 :
  1593. sprintf(szClass, "Class2");
  1594. break;
  1595. case MODEM_CLASS2_0 :
  1596. sprintf(szClass, "Class2_0");
  1597. break;
  1598. default:
  1599. sprintf(szClass, "Class1");
  1600. }
  1601. //
  1602. // depending on a requested operation, find the appropriate settings
  1603. //
  1604. if (pTG->Operation == T30_RX)
  1605. {
  1606. KeyList[0] = dwKey;
  1607. sprintf(KeyName, "%s\\%s", pTG->FComModem.rgchKey, szClass);
  1608. KeyList[1] = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_READ);
  1609. sprintf(KeyName, "%s\\%s\\AdaptiveAnswer", pTG->FComModem.rgchKey, szClass);
  1610. KeyList[2] = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_READ);
  1611. if (KeyList[2] == 0)
  1612. {
  1613. pTG->AdaptiveAnswerEnable = 0;
  1614. sprintf(KeyName, "%s\\%s\\Receive", pTG->FComModem.rgchKey, szClass);
  1615. KeyList[2] = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_READ);
  1616. }
  1617. else
  1618. {
  1619. dwKeyAdaptiveAnswer = KeyList[2];
  1620. pTG->AdaptiveAnswerEnable = 1;
  1621. }
  1622. KeyList[3] = 0;
  1623. //
  1624. // Turn off adaptive answering if the admin disabled it via the UI
  1625. //
  1626. pTG->AdaptiveAnswerEnable = pTG->AdaptiveAnswerEnable && pTG->ExtData.bAdaptiveAnsweringEnabled;
  1627. }
  1628. else if (pTG->Operation == T30_TX)
  1629. {
  1630. KeyList[0] = dwKey;
  1631. sprintf(KeyName, "%s\\%s", pTG->FComModem.rgchKey, szClass);
  1632. KeyList[1] = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_READ);
  1633. sprintf(KeyName, "%s\\%s\\Send", pTG->FComModem.rgchKey, szClass);
  1634. KeyList[2] = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_READ);
  1635. KeyList[3] = 0;
  1636. }
  1637. else
  1638. {
  1639. DebugPrintEx(DEBUG_ERR, "INVALID pTG->Operation=%d",(int)pTG->Operation );
  1640. goto end;
  1641. }
  1642. if (lpMdmCaps->uClasses = (USHORT)ProfileListGetInt(KeyList, szModemFaxClasses, 0))
  1643. {
  1644. pTG->TmpSettings.dwGot |= fGOTCAP_CLASSES;
  1645. }
  1646. if(lpMdmCaps->uClasses & FAXCLASS1)
  1647. {
  1648. if (lpMdmCaps->uSendSpeeds = (USHORT)ProfileListGetInt(KeyList, szModemSendSpeeds, 0))
  1649. {
  1650. pTG->TmpSettings.dwGot |= fGOTCAP_SENDSPEEDS;
  1651. }
  1652. if (lpMdmCaps->uRecvSpeeds = (USHORT)ProfileListGetInt(KeyList, szModemRecvSpeeds, 0))
  1653. {
  1654. pTG->TmpSettings.dwGot |= fGOTCAP_RECVSPEEDS;
  1655. }
  1656. }
  1657. pTG->ModemKeyCreationId = ProfileGetInt(dwKey, szModemKeyCreationId, 0, FALSE);
  1658. //RSL 10/10/96
  1659. pTG->Inst.ProtParams.fEnableV17Send = ProfileListGetInt(KeyList, szEnableV17Send, 1);
  1660. if (IsCacheIntDirty(UnimodemFaxKey,szEnableV17Send,pTG->Inst.ProtParams.fEnableV17Send))
  1661. {
  1662. DebugPrintEx(DEBUG_WRN, "EnableV17Send cached settings are invalid, need to re-install the modem.");
  1663. fRet = FALSE;
  1664. goto end;
  1665. }
  1666. pTG->Inst.ProtParams.fEnableV17Recv = ProfileListGetInt(KeyList, szEnableV17Recv, 1);
  1667. if (IsCacheIntDirty(UnimodemFaxKey,szEnableV17Recv,pTG->Inst.ProtParams.fEnableV17Recv))
  1668. {
  1669. DebugPrintEx(DEBUG_WRN, "EnableV17Recv cached settings are invalid, need to re-install the modem.");
  1670. fRet = FALSE;
  1671. goto end;
  1672. }
  1673. uTmp = ProfileListGetInt(KeyList, szHighestSendSpeed, 0);
  1674. if (IsCacheIntDirty(UnimodemFaxKey,szHighestSendSpeed,uTmp))
  1675. {
  1676. DebugPrintEx(DEBUG_WRN, "HighestSendSpeed cached settings are invalid, need to re-install the modem.");
  1677. fRet = FALSE;
  1678. goto end;
  1679. }
  1680. if (uTmp)
  1681. {
  1682. pTG->Inst.ProtParams.HighestSendSpeed = (SHORT)uTmp;
  1683. }
  1684. uTmp = ProfileListGetInt(KeyList, szLowestSendSpeed, 0);
  1685. if (IsCacheIntDirty(UnimodemFaxKey,szLowestSendSpeed,uTmp))
  1686. {
  1687. DebugPrintEx(DEBUG_WRN, "LowestSendSpeed cached settings are invalid, need to re-install the modem.");
  1688. fRet = FALSE;
  1689. goto end;
  1690. }
  1691. if (uTmp)
  1692. {
  1693. pTG->Inst.ProtParams.LowestSendSpeed = (SHORT)uTmp;
  1694. }
  1695. uTmp = ProfileListGetInt(KeyList, szSerialSpeedInit, 0);
  1696. if (IsCacheIntDirty(UnimodemFaxKey,szSerialSpeedInit,uTmp))
  1697. {
  1698. DebugPrintEx(DEBUG_WRN, "SerialSpeedInit cached settings are invalid, need to re-install the modem.");
  1699. fRet = FALSE;
  1700. goto end;
  1701. }
  1702. if (uTmp)
  1703. {
  1704. pTG->SerialSpeedInit = (UWORD)uTmp;
  1705. pTG->SerialSpeedInitSet = 1;
  1706. pTG->TmpSettings.dwGot |= fGOTPARM_PORTSPEED;
  1707. }
  1708. uTmp = ProfileListGetInt(KeyList, szSerialSpeedConnect, 0);
  1709. if (uTmp)
  1710. {
  1711. pTG->SerialSpeedConnect = (UWORD)uTmp;
  1712. pTG->SerialSpeedConnectSet = 1;
  1713. pTG->TmpSettings.dwGot |= fGOTPARM_PORTSPEED;
  1714. }
  1715. uTmp = ProfileListGetInt(KeyList, szHardwareFlowControl, 0);
  1716. if (IsCacheIntDirty(UnimodemFaxKey,szHardwareFlowControl,uTmp))
  1717. {
  1718. DebugPrintEx(DEBUG_WRN, "HardwareFlowControl cached settings are invalid, need to re-install the modem.");
  1719. fRet = FALSE;
  1720. goto end;
  1721. }
  1722. if (uTmp)
  1723. {
  1724. pTG->fEnableHardwareFlowControl = 1;
  1725. }
  1726. DebugPrintEx( DEBUG_MSG,
  1727. "fEnableV17Send=%d, fEnableV17Recv=%d, "
  1728. "HighestSendSpeed=%d, Low=%d EnableAdaptAnswer=%d",
  1729. pTG->Inst.ProtParams.fEnableV17Send,
  1730. pTG->Inst.ProtParams.fEnableV17Recv,
  1731. pTG->Inst.ProtParams.HighestSendSpeed,
  1732. pTG->Inst.ProtParams.LowestSendSpeed,
  1733. pTG->AdaptiveAnswerEnable);
  1734. DebugPrintEx( DEBUG_MSG,
  1735. "HardwareFlowControl=%d, SerialSpeedInit=%d, SerialSpeedConnect=%d",
  1736. pTG->fEnableHardwareFlowControl,
  1737. pTG->SerialSpeedInit,
  1738. pTG->SerialSpeedConnect);
  1739. // get CmdTab. We distinguish been a command being not-specified and null.
  1740. //
  1741. if (imodem_list_get_str(pTG,KeyList,szResetCommand,pTG->TmpSettings.szReset,MAXCMDSIZE,TRUE))
  1742. {
  1743. pTG->TmpSettings.dwGot |= fGOTCMD_Reset;
  1744. }
  1745. if (IsCacheStringDirty(UnimodemFaxKey,szResetCommand,pTG->TmpSettings.szReset))
  1746. {
  1747. DebugPrintEx(DEBUG_WRN, "ResetCommand cached settings are invalid, need to re-install the modem.");
  1748. fRet = FALSE;
  1749. goto end;
  1750. }
  1751. if (imodem_list_get_str(pTG,KeyList,szSetupCommand,pTG->TmpSettings.szSetup,MAXCMDSIZE,TRUE))
  1752. {
  1753. pTG->TmpSettings.dwGot |= fGOTCMD_Setup;
  1754. }
  1755. if (IsCacheStringDirty(UnimodemFaxKey,szSetupCommand,pTG->TmpSettings.szSetup))
  1756. {
  1757. DebugPrintEx(DEBUG_WRN, "SetupCommand cached settings are invalid, need to re-install the modem.");
  1758. fRet = FALSE;
  1759. goto end;
  1760. }
  1761. if (imodem_list_get_str(pTG,KeyList,szResetCommandGenerated,pTG->TmpSettings.szResetGenerated,MAXCMDSIZE,TRUE))
  1762. {
  1763. DebugPrintEx(DEBUG_MSG, "Will use generated ResetCommand %s", pTG->TmpSettings.szResetGenerated);
  1764. }
  1765. if (imodem_list_get_str(pTG,KeyList,szSetupCommandGenerated,pTG->TmpSettings.szSetupGenerated,MAXCMDSIZE,TRUE))
  1766. {
  1767. DebugPrintEx(DEBUG_MSG, "Will use generated SetupCommand %s", pTG->TmpSettings.szSetupGenerated);
  1768. }
  1769. if (imodem_list_get_str(pTG,KeyList,szPreDialCommand,pTG->TmpSettings.szPreDial,MAXCMDSIZE,TRUE))
  1770. {
  1771. pTG->TmpSettings.dwGot |= fGOTCMD_PreDial;
  1772. }
  1773. if (IsCacheStringDirty(UnimodemFaxKey,szPreDialCommand,pTG->TmpSettings.szPreDial))
  1774. {
  1775. DebugPrintEx(DEBUG_WRN, "PreDialCommand cached settings are invalid, need to re-install the modem.");
  1776. fRet = FALSE;
  1777. goto end;
  1778. }
  1779. if (imodem_list_get_str(pTG,KeyList,szPreAnswerCommand,pTG->TmpSettings.szPreAnswer,MAXCMDSIZE,TRUE))
  1780. {
  1781. pTG->TmpSettings.dwGot |= fGOTCMD_PreAnswer;
  1782. }
  1783. if (IsCacheStringDirty(UnimodemFaxKey,szPreAnswerCommand,pTG->TmpSettings.szPreAnswer))
  1784. {
  1785. DebugPrintEx(DEBUG_WRN, "PreAnswerCommand cached settings are invalid, need to re-install the modem.");
  1786. fRet = FALSE;
  1787. goto end;
  1788. }
  1789. if (imodem_list_get_str(pTG,KeyList,szExitCommand,pTG->TmpSettings.szExit,MAXCMDSIZE,TRUE))
  1790. {
  1791. pTG->TmpSettings.dwGot |= fGOTCMD_PreExit;
  1792. }
  1793. if (IsCacheStringDirty(UnimodemFaxKey,szExitCommand,pTG->TmpSettings.szExit))
  1794. {
  1795. DebugPrintEx(DEBUG_WRN, "ExitCommand cached settings are invalid, need to re-install the modem.");
  1796. fRet = FALSE;
  1797. goto end;
  1798. }
  1799. //
  1800. // Adaptive Answer strings ONLY.
  1801. //
  1802. if (pTG->AdaptiveAnswerEnable)
  1803. {
  1804. pTG->AnswerCommandNum = 0;
  1805. // get Answer commands key
  1806. sprintf(KeyName, "%s\\Class1\\AdaptiveAnswer\\AnswerCommand", pTG->FComModem.rgchKey);
  1807. dwKeyAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_READ);
  1808. if (dwKeyAnswer == 0)
  1809. {
  1810. DebugPrintEx(DEBUG_ERR, "AdaptiveAnswer\\AnswerCommand does not exist");
  1811. goto lPostAdaptiveAnswer;
  1812. }
  1813. for (i=1; i<=20; i++)
  1814. {
  1815. sprintf (KeyName, "%d", i);
  1816. if ( ! imodem_get_str(pTG, dwKeyAnswer, KeyName, lpTemp, MAXCMDSIZE, TRUE) )
  1817. {
  1818. break;
  1819. }
  1820. if (NULL != (pTG->AnswerCommand[pTG->AnswerCommandNum] = MemAlloc( strlen(lpTemp) + 1)))
  1821. {
  1822. strcpy ( pTG->AnswerCommand[pTG->AnswerCommandNum], lpTemp);
  1823. }
  1824. else
  1825. {
  1826. goto end;
  1827. }
  1828. pTG->AnswerCommandNum++;
  1829. }
  1830. ProfileClose(dwKeyAnswer);
  1831. if (pTG->AnswerCommandNum == 0)
  1832. {
  1833. DebugPrintEx(DEBUG_ERR, "AdaptiveAnswer\\AnswerCommand Zero values.");
  1834. goto lPostAdaptiveAnswer;
  1835. }
  1836. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szModemResponseFaxDetect, lpTemp, MAXCMDSIZE, FALSE) )
  1837. {
  1838. if (NULL != (pTG->ModemResponseFaxDetect = MemAlloc( strlen(lpTemp) + 1)))
  1839. strcpy ( pTG->ModemResponseFaxDetect, lpTemp);
  1840. else
  1841. goto end;
  1842. }
  1843. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szModemResponseDataDetect, lpTemp, MAXCMDSIZE, FALSE) )
  1844. {
  1845. if (NULL != (pTG->ModemResponseDataDetect = MemAlloc( strlen(lpTemp) + 1)))
  1846. strcpy ( pTG->ModemResponseDataDetect, lpTemp);
  1847. else
  1848. goto end;
  1849. }
  1850. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szSerialSpeedFaxDetect, lpTemp, MAXCMDSIZE, FALSE) )
  1851. {
  1852. pTG->SerialSpeedFaxDetect = (UWORD)atoi (lpTemp);
  1853. }
  1854. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szSerialSpeedDataDetect, lpTemp, MAXCMDSIZE, FALSE) )
  1855. {
  1856. pTG->SerialSpeedDataDetect = (UWORD)atoi (lpTemp);
  1857. }
  1858. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szHostCommandFaxDetect, lpTemp, MAXCMDSIZE, TRUE) )
  1859. {
  1860. if (NULL != (pTG->HostCommandFaxDetect = MemAlloc( strlen(lpTemp) + 1)))
  1861. strcpy ( pTG->HostCommandFaxDetect, lpTemp);
  1862. else
  1863. goto end;
  1864. }
  1865. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szHostCommandDataDetect, lpTemp, MAXCMDSIZE, TRUE) )
  1866. {
  1867. if (NULL != (pTG->HostCommandDataDetect = MemAlloc( strlen(lpTemp) + 1)))
  1868. strcpy ( pTG->HostCommandDataDetect, lpTemp);
  1869. else
  1870. goto end;
  1871. }
  1872. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szModemResponseFaxConnect, lpTemp, MAXCMDSIZE, FALSE) )
  1873. {
  1874. if (NULL != (pTG->ModemResponseFaxConnect = MemAlloc( strlen(lpTemp) + 1)))
  1875. strcpy ( pTG->ModemResponseFaxConnect, lpTemp);
  1876. else
  1877. goto end;
  1878. }
  1879. if ( imodem_get_str(pTG, dwKeyAdaptiveAnswer, szModemResponseDataConnect, lpTemp, MAXCMDSIZE, FALSE) )
  1880. {
  1881. if (NULL != (pTG->ModemResponseDataConnect = MemAlloc( strlen(lpTemp) + 1)))
  1882. strcpy ( pTG->ModemResponseDataConnect, lpTemp);
  1883. else
  1884. goto end;
  1885. }
  1886. }
  1887. lPostAdaptiveAnswer:
  1888. pTG->FixSerialSpeed = (UWORD)ProfileListGetInt(KeyList, szFixSerialSpeed, 0);
  1889. if (pTG->FixSerialSpeed)
  1890. {
  1891. pTG->TmpSettings.dwGot |= fGOTPARM_PORTSPEED;
  1892. pTG->FixSerialSpeedSet = 1;
  1893. }
  1894. if (IsCacheIntDirty(UnimodemFaxKey,szFixSerialSpeed,pTG->FixSerialSpeed))
  1895. {
  1896. DebugPrintEx(DEBUG_WRN, "FixSerialSpeed cached settings are invalid, need to re-install the modem.");
  1897. fRet = FALSE;
  1898. goto end;
  1899. }
  1900. //
  1901. // Merge 3 optional different settings for Serial Speed here
  1902. //
  1903. // FixSerialSpeed overrides the others (init/connect)
  1904. if (pTG->FixSerialSpeedSet)
  1905. {
  1906. pTG->SerialSpeedInit = pTG->FixSerialSpeed;
  1907. pTG->SerialSpeedConnect = pTG->FixSerialSpeed;
  1908. pTG->SerialSpeedInitSet = 1;
  1909. pTG->SerialSpeedConnectSet = 1;
  1910. }
  1911. // if only one of init/connect then the other is same
  1912. if ( pTG->SerialSpeedInitSet && (!pTG->SerialSpeedConnectSet) )
  1913. {
  1914. pTG->SerialSpeedConnect = pTG->SerialSpeedInit;
  1915. pTG->SerialSpeedConnectSet = 1;
  1916. }
  1917. else if ( (!pTG->SerialSpeedInitSet) && pTG->SerialSpeedConnectSet )
  1918. {
  1919. pTG->SerialSpeedInit = pTG->SerialSpeedConnect;
  1920. pTG->SerialSpeedInitSet = 1;
  1921. }
  1922. // values init/connect are always initialized.
  1923. // Use (init/connect)Set flags to determine whether there were originally set.
  1924. if (! pTG->SerialSpeedInit)
  1925. {
  1926. pTG->SerialSpeedInit = 57600;
  1927. pTG->SerialSpeedConnect = 57600;
  1928. }
  1929. // +++ Expand as necessary:
  1930. if (ProfileListGetInt(KeyList, szCL1_NO_SYNC_IF_CMD, 1))
  1931. {
  1932. pTG->TmpSettings.dwFlags |= fMDMSP_C1_NO_SYNC_IF_CMD;
  1933. }
  1934. if (ProfileListGetInt(KeyList, szANS_GOCLASS_TWICE, 1))
  1935. {
  1936. pTG->TmpSettings.dwFlags |= fMDMSP_ANS_GOCLASS_TWICE; // DEFAULT
  1937. }
  1938. #define szMDMSP_C1_FCS "Cl1FCS" // 0==dunno 1=NO 2=yes-bad
  1939. // specifies whether the modem reports the 2-byteFCS with
  1940. // received HDLC data. (Elliot bugs# 3641, 3668, 3086 report
  1941. // cases of modems sending incorrect FCS bytes).
  1942. // 9/7/95 JosephJ -- changed default from 0 to 2 because Class1 spec
  1943. // says we should NOT rely on the FCS bytes being computed correctly.
  1944. switch(ProfileListGetInt(KeyList, szMDMSP_C1_FCS, 2))
  1945. {
  1946. case 1: pTG->TmpSettings.dwFlags |= fMDMSP_C1_FCS_NO;
  1947. break;
  1948. case 2: pTG->TmpSettings.dwFlags |= fMDMSP_C1_FCS_YES_BAD;
  1949. break;
  1950. }
  1951. pTG->TmpSettings.dwGot |= fGOTFLAGS;
  1952. // Retrieve ID command.
  1953. // a way around this Id check. If IdCmd has been manually deleted, skip chk
  1954. if (imodem_list_get_str(pTG, KeyList, szModemIdCmd,
  1955. pTG->TmpSettings.szIDCmd, MAXCMDSIZE, TRUE))
  1956. {
  1957. pTG->TmpSettings.dwGot |= fGOTPARM_IDCMD;
  1958. if (imodem_list_get_str(pTG, KeyList, szModemId,
  1959. pTG->TmpSettings.szID, MAXIDSIZE, FALSE))
  1960. pTG->TmpSettings.dwGot |= fGOTPARM_ID;
  1961. }
  1962. pTG->TmpSettings.uDontPurge= (USHORT)ProfileListGetInt(KeyList, szDONT_PURGE, 0xff);
  1963. //
  1964. // Classes 2 and 2.0
  1965. //
  1966. if (pTG->ModemClass != MODEM_CLASS1)
  1967. {
  1968. uTmp = ProfileListGetInt(KeyList,szRECV_BOR, CL2_DEFAULT_SETTING);
  1969. pTG->CurrentMFRSpec.iReceiveBOR = (USHORT) uTmp;
  1970. uTmp = ProfileListGetInt(KeyList, szSEND_BOR, CL2_DEFAULT_SETTING);
  1971. pTG->CurrentMFRSpec.iSendBOR = (USHORT) uTmp;
  1972. uTmp = ProfileListGetInt(KeyList, szSW_BOR, CL2_DEFAULT_SETTING);
  1973. pTG->CurrentMFRSpec.fSWFBOR = (BOOL) uTmp;
  1974. uTmp = ProfileListGetInt(KeyList, szDC2CHAR, CL2_DEFAULT_SETTING);
  1975. pTG->CurrentMFRSpec.szDC2[0] = (CHAR) uTmp;
  1976. uTmp = ProfileListGetInt(KeyList, szIS_SIERRA, CL2_DEFAULT_SETTING);
  1977. pTG->CurrentMFRSpec.bIsSierra = (BOOL) uTmp;
  1978. uTmp = ProfileListGetInt(KeyList, szIS_EXAR, CL2_DEFAULT_SETTING);
  1979. pTG->CurrentMFRSpec.bIsExar = (BOOL) uTmp;
  1980. uTmp = ProfileListGetInt(KeyList, szSKIP_CTRL_Q, CL2_DEFAULT_SETTING);
  1981. pTG->CurrentMFRSpec.fSkipCtrlQ = (BOOL) uTmp;
  1982. }
  1983. if (dwKey)
  1984. ProfileClose(dwKey);
  1985. #define fMANDATORY (fGOTCMD_Reset|fGOTCMD_Setup|fGOTCAP_CLASSES)
  1986. #define fCLASS1MANDATORY (fMANDATORY | fGOTCAP_SENDSPEEDS | fGOTCAP_RECVSPEEDS)
  1987. fRet = (lpMdmCaps->uClasses & FAXCLASS1)
  1988. ? ((pTG->TmpSettings.dwGot & fCLASS1MANDATORY) == fCLASS1MANDATORY)
  1989. : ((pTG->TmpSettings.dwGot & fMANDATORY) == fMANDATORY);
  1990. end:
  1991. for (i=1; i<10; i++)
  1992. {
  1993. if (KeyList[i] != 0)
  1994. {
  1995. ProfileClose (KeyList[i]);
  1996. }
  1997. }
  1998. if (UnimodemFaxKey)
  1999. {
  2000. ProfileClose(UnimodemFaxKey);
  2001. }
  2002. if (!fRet)
  2003. { // Lets free all memory that was allocated here
  2004. CleanModemInfStrings (pTG);
  2005. }
  2006. return fRet;
  2007. }
  2008. void SaveCl2Settings(PThrdGlbl pTG, DWORD_PTR dwKey)
  2009. {
  2010. DEBUG_FUNCTION_NAME(("SaveCl2Settings"));
  2011. if (pTG->ModemClass != MODEM_CLASS1)
  2012. {
  2013. if (pTG->CurrentMFRSpec.iReceiveBOR != CL2_DEFAULT_SETTING)
  2014. {
  2015. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.iReceiveBOR);
  2016. ProfileWriteString(dwKey, szRECV_BOR, pTG->TmpSettings.szSmallTemp1, FALSE);
  2017. }
  2018. if (pTG->CurrentMFRSpec.iSendBOR != CL2_DEFAULT_SETTING)
  2019. {
  2020. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.iSendBOR);
  2021. ProfileWriteString(dwKey, szSEND_BOR, pTG->TmpSettings.szSmallTemp1, FALSE);
  2022. }
  2023. if (pTG->CurrentMFRSpec.fSWFBOR != CL2_DEFAULT_SETTING)
  2024. {
  2025. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.fSWFBOR);
  2026. ProfileWriteString(dwKey, szSW_BOR, pTG->TmpSettings.szSmallTemp1, FALSE);
  2027. }
  2028. if (pTG->CurrentMFRSpec.szDC2[0] != (CHAR)CL2_DEFAULT_SETTING)
  2029. {
  2030. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.szDC2[0]);
  2031. ProfileWriteString(dwKey, szDC2CHAR, pTG->TmpSettings.szSmallTemp1, FALSE);
  2032. }
  2033. if (pTG->CurrentMFRSpec.bIsSierra != CL2_DEFAULT_SETTING)
  2034. {
  2035. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.bIsSierra);
  2036. ProfileWriteString(dwKey, szIS_SIERRA, pTG->TmpSettings.szSmallTemp1, FALSE);
  2037. }
  2038. if (pTG->CurrentMFRSpec.bIsExar != CL2_DEFAULT_SETTING)
  2039. {
  2040. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.bIsExar);
  2041. ProfileWriteString(dwKey, szIS_EXAR, pTG->TmpSettings.szSmallTemp1, FALSE);
  2042. }
  2043. if (pTG->CurrentMFRSpec.fSkipCtrlQ != CL2_DEFAULT_SETTING)
  2044. {
  2045. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->CurrentMFRSpec.fSkipCtrlQ);
  2046. ProfileWriteString(dwKey, szSKIP_CTRL_Q, pTG->TmpSettings.szSmallTemp1, FALSE);
  2047. }
  2048. }
  2049. }
  2050. BOOL iModemSaveCurrentModemInfo(PThrdGlbl pTG)
  2051. {
  2052. DWORD_PTR dwKey=0;
  2053. LPMODEMCAPS lpMdmCaps = pTG->TmpSettings.lpMdmCaps;
  2054. char KeyName[200];
  2055. DWORD_PTR dwKeyAdaptiveAnswer=0;
  2056. DWORD_PTR dwKeyAnswer=0;
  2057. DWORD i;
  2058. char szClass[10];
  2059. DEBUG_FUNCTION_NAME(("iModemSaveCurrentModemInfo"));
  2060. //
  2061. // Right now we save all major caps at the root level.
  2062. //
  2063. if (!(dwKey=ProfileOpen(pTG->FComModem.dwProfileID, pTG->FComModem.rgchKey,
  2064. fREG_CREATE | fREG_READ | fREG_WRITE)))
  2065. {
  2066. DebugPrintEx(DEBUG_ERR,"Couldn't get location of modem info.");
  2067. goto failure;
  2068. }
  2069. if (! pTG->ModemClass)
  2070. {
  2071. pTG->ModemClass = MODEM_CLASS1;
  2072. DebugPrintEx(DEBUG_ERR, "MODEM CLASS was not defined.");
  2073. }
  2074. switch (pTG->ModemClass)
  2075. {
  2076. case MODEM_CLASS1 :
  2077. ProfileWriteString(dwKey, szFixModemClass, "1", TRUE);
  2078. sprintf(szClass, "Class1");
  2079. break;
  2080. case MODEM_CLASS2 :
  2081. sprintf(szClass, "Class2");
  2082. ProfileWriteString(dwKey, szFixModemClass, "2", TRUE);
  2083. break;
  2084. case MODEM_CLASS2_0 :
  2085. sprintf(szClass, "Class2_0");
  2086. ProfileWriteString(dwKey, szFixModemClass, "20", TRUE);
  2087. break;
  2088. default:
  2089. sprintf(szClass, "Class1");
  2090. }
  2091. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->ModemKeyCreationId );
  2092. ProfileWriteString(dwKey, szModemKeyCreationId, pTG->TmpSettings.szSmallTemp1, FALSE);
  2093. ////// Modem Commands
  2094. ProfileWriteString(dwKey, szResetCommand, pTG->TmpSettings.szReset, TRUE);
  2095. ProfileWriteString(dwKey, szResetCommandGenerated, pTG->TmpSettings.szResetGenerated, TRUE);
  2096. ProfileWriteString(dwKey, szSetupCommand, pTG->TmpSettings.szSetup, TRUE);
  2097. ProfileWriteString(dwKey, szSetupCommandGenerated, pTG->TmpSettings.szSetupGenerated, TRUE);
  2098. ProfileWriteString(dwKey, szExitCommand , pTG->TmpSettings.szExit, TRUE);
  2099. ProfileWriteString(dwKey, szPreDialCommand , pTG->TmpSettings.szPreDial, TRUE);
  2100. ProfileWriteString(dwKey, szPreAnswerCommand, pTG->TmpSettings.szPreAnswer, TRUE);
  2101. //
  2102. // Adaptive Answer
  2103. //
  2104. if (pTG->AdaptiveAnswerEnable)
  2105. {
  2106. // create Class key if it doesn't exist
  2107. sprintf(KeyName, "%s\\%s", pTG->FComModem.rgchKey, szClass);
  2108. dwKeyAdaptiveAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_CREATE | fREG_READ | fREG_WRITE);
  2109. if (dwKeyAdaptiveAnswer == 0)
  2110. {
  2111. DebugPrintEx(DEBUG_ERR,"couldn't open Class1.");
  2112. goto failure;
  2113. }
  2114. ProfileClose(dwKeyAdaptiveAnswer);
  2115. // create Class1\AdaptiveAnswer key if it doesn't exist
  2116. sprintf(KeyName, "%s\\%s\\AdaptiveAnswer", pTG->FComModem.rgchKey, szClass);
  2117. dwKeyAdaptiveAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_CREATE | fREG_READ | fREG_WRITE);
  2118. if (dwKeyAdaptiveAnswer == 0)
  2119. {
  2120. DebugPrintEx(DEBUG_ERR,"couldn't open AdaptiveAnswer.");
  2121. goto failure;
  2122. }
  2123. // create Class1\AdaptiveAnswer\Answer key if it doesn't exist
  2124. sprintf(KeyName, "%s\\%s\\AdaptiveAnswer\\AnswerCommand", pTG->FComModem.rgchKey, szClass);
  2125. dwKeyAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_CREATE | fREG_READ | fREG_WRITE);
  2126. if (dwKeyAnswer == 0)
  2127. {
  2128. DebugPrintEx(DEBUG_ERR,"couldn't open AdaptiveAnswer\\AnswerCommand .");
  2129. goto failure;
  2130. }
  2131. for (i=0; i<pTG->AnswerCommandNum; i++)
  2132. {
  2133. sprintf (KeyName, "%d", i+1);
  2134. ProfileWriteString (dwKeyAnswer, KeyName , pTG->AnswerCommand[i], TRUE );
  2135. }
  2136. ProfileClose(dwKeyAnswer);
  2137. // store the rest of the AdaptiveAnswer values
  2138. if (pTG->ModemResponseFaxDetect)
  2139. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseFaxDetect, pTG->ModemResponseFaxDetect, FALSE);
  2140. if (pTG->ModemResponseDataDetect)
  2141. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseDataDetect, pTG->ModemResponseDataDetect, FALSE);
  2142. if (pTG->SerialSpeedFaxDetect)
  2143. {
  2144. sprintf (KeyName, "%d", pTG->SerialSpeedFaxDetect);
  2145. ProfileWriteString (dwKeyAdaptiveAnswer, szSerialSpeedFaxDetect, KeyName, FALSE);
  2146. }
  2147. if (pTG->SerialSpeedDataDetect)
  2148. {
  2149. sprintf (KeyName, "%d", pTG->SerialSpeedDataDetect);
  2150. ProfileWriteString (dwKeyAdaptiveAnswer, szSerialSpeedDataDetect, KeyName, FALSE);
  2151. }
  2152. if (pTG->HostCommandFaxDetect)
  2153. ProfileWriteString (dwKeyAdaptiveAnswer, szHostCommandFaxDetect, pTG->HostCommandFaxDetect, TRUE);
  2154. if (pTG->HostCommandDataDetect)
  2155. ProfileWriteString (dwKeyAdaptiveAnswer, szHostCommandDataDetect, pTG->HostCommandDataDetect, TRUE);
  2156. if (pTG->ModemResponseFaxConnect)
  2157. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseFaxConnect, pTG->ModemResponseFaxConnect, FALSE);
  2158. if (pTG->ModemResponseDataConnect)
  2159. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseDataConnect, pTG->ModemResponseDataConnect, FALSE);
  2160. ProfileClose(dwKeyAdaptiveAnswer);
  2161. }
  2162. if (pTG->fEnableHardwareFlowControl)
  2163. {
  2164. ProfileWriteString (dwKey, szHardwareFlowControl, "1", FALSE);
  2165. }
  2166. //
  2167. // Serial Speed
  2168. //
  2169. if (!pTG->SerialSpeedInitSet)
  2170. {
  2171. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->TmpSettings.dwSerialSpeed);
  2172. ProfileWriteString(dwKey, szFixSerialSpeed, pTG->TmpSettings.szSmallTemp1, FALSE);
  2173. }
  2174. else
  2175. {
  2176. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->SerialSpeedInit);
  2177. ProfileWriteString(dwKey, szSerialSpeedInit, pTG->TmpSettings.szSmallTemp1, FALSE);
  2178. }
  2179. if (pTG->TmpSettings.dwGot & fGOTFLAGS)
  2180. {
  2181. if (pTG->TmpSettings.dwFlags & fMDMSP_C1_NO_SYNC_IF_CMD)
  2182. {
  2183. ProfileWriteString(dwKey, szCL1_NO_SYNC_IF_CMD, "1", FALSE);
  2184. }
  2185. if (!(pTG->TmpSettings.dwFlags & fMDMSP_ANS_GOCLASS_TWICE))
  2186. {
  2187. ProfileWriteString(dwKey, szANS_GOCLASS_TWICE, "0", FALSE);
  2188. }
  2189. }
  2190. // uDontPurge==1 => save 1
  2191. // otherwise => save 0
  2192. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) (pTG->TmpSettings.uDontPurge==1)?1:0);
  2193. ProfileWriteString(dwKey, szDONT_PURGE, pTG->TmpSettings.szSmallTemp1, FALSE);
  2194. ///////// Modem Caps...
  2195. // write out Classes, then Speeds
  2196. wsprintf(pTG->TmpSettings.szSmallTemp1, "%u", (unsigned) lpMdmCaps->uClasses);
  2197. ProfileWriteString(dwKey, szModemFaxClasses, pTG->TmpSettings.szSmallTemp1, FALSE);
  2198. // Classes 2 and 2.0
  2199. SaveCl2Settings(pTG, dwKey);
  2200. if(lpMdmCaps->uClasses & FAXCLASS1)
  2201. {
  2202. wsprintf(pTG->TmpSettings.szSmallTemp1, "%u", (unsigned) lpMdmCaps->uSendSpeeds);
  2203. ProfileWriteString(dwKey, szModemSendSpeeds, pTG->TmpSettings.szSmallTemp1, FALSE);
  2204. wsprintf(pTG->TmpSettings.szSmallTemp1, "%u", (unsigned) lpMdmCaps->uRecvSpeeds);
  2205. ProfileWriteString(dwKey, szModemRecvSpeeds, pTG->TmpSettings.szSmallTemp1, FALSE);
  2206. }
  2207. if (dwKey)
  2208. ProfileClose(dwKey);
  2209. return TRUE;
  2210. failure:
  2211. if (dwKey)
  2212. ProfileClose(dwKey);
  2213. return FALSE;
  2214. }
  2215. BOOL ReadModemClassFromRegistry (PThrdGlbl pTG)
  2216. {
  2217. UINT uTmp;
  2218. DWORD_PTR dwKey;
  2219. if ( ! (dwKey = ProfileOpen(pTG->FComModem.dwProfileID, pTG->FComModem.rgchKey, fREG_READ)))
  2220. {
  2221. return FALSE;
  2222. }
  2223. //
  2224. // Lets see what modem Class we will use
  2225. //
  2226. uTmp = ProfileGetInt(dwKey, szFixModemClass, 0, FALSE);
  2227. if (uTmp == 1)
  2228. {
  2229. pTG->ModemClass = MODEM_CLASS1;
  2230. }
  2231. else if (uTmp == 2)
  2232. {
  2233. pTG->ModemClass = MODEM_CLASS2;
  2234. }
  2235. else if (uTmp == 20)
  2236. {
  2237. pTG->ModemClass = MODEM_CLASS2_0;
  2238. }
  2239. if (dwKey)
  2240. ProfileClose(dwKey);
  2241. return TRUE;
  2242. }
  2243. BOOL SaveModemClass2Registry(PThrdGlbl pTG)
  2244. {
  2245. DWORD_PTR dwKey=0;
  2246. DEBUG_FUNCTION_NAME(("SaveModemClass2Registry"));
  2247. if (!(dwKey=ProfileOpen(pTG->FComModem.dwProfileID, pTG->FComModem.rgchKey,
  2248. fREG_CREATE | fREG_READ | fREG_WRITE)))
  2249. {
  2250. DebugPrintEx(DEBUG_ERR,"Couldn't get location of modem info.");
  2251. goto failure;
  2252. }
  2253. switch (pTG->ModemClass)
  2254. {
  2255. case MODEM_CLASS1 :
  2256. ProfileWriteString(dwKey, szFixModemClass, "1", TRUE);
  2257. break;
  2258. case MODEM_CLASS2 :
  2259. ProfileWriteString(dwKey, szFixModemClass, "2", TRUE);
  2260. break;
  2261. case MODEM_CLASS2_0 :
  2262. ProfileWriteString(dwKey, szFixModemClass, "20", TRUE);
  2263. break;
  2264. default:
  2265. DebugPrintEx(DEBUG_ERR,"pTG->ModemClass=%d", pTG->ModemClass);
  2266. ProfileWriteString(dwKey, szFixModemClass, "1", TRUE);
  2267. }
  2268. if (dwKey)
  2269. ProfileClose(dwKey);
  2270. return TRUE;
  2271. failure:
  2272. return FALSE;
  2273. }
  2274. BOOL SaveInf2Registry (PThrdGlbl pTG)
  2275. {
  2276. DWORD_PTR dwKey=0;
  2277. LPMODEMCAPS lpMdmCaps = pTG->TmpSettings.lpMdmCaps;
  2278. char KeyName[200];
  2279. DWORD_PTR dwKeyAdaptiveAnswer=0;
  2280. DWORD_PTR dwKeyAnswer=0;
  2281. DWORD i;
  2282. char szClass[10];
  2283. DEBUG_FUNCTION_NAME(("SaveInf2Registry"));
  2284. if (!(dwKey=ProfileOpen(pTG->FComModem.dwProfileID, pTG->FComModem.rgchKey,
  2285. fREG_CREATE | fREG_READ | fREG_WRITE)))
  2286. {
  2287. DebugPrintEx(DEBUG_ERR,"Couldn't get location of modem info.");
  2288. goto failure;
  2289. }
  2290. if (! pTG->ModemClass)
  2291. {
  2292. DebugPrintEx(DEBUG_ERR,"MODEM CLASS was not defined.");
  2293. }
  2294. switch (pTG->ModemClass)
  2295. {
  2296. case MODEM_CLASS1 :
  2297. sprintf(szClass, "Class1");
  2298. ProfileWriteString(dwKey, szFixModemClass, "1", TRUE);
  2299. break;
  2300. case MODEM_CLASS2 :
  2301. sprintf(szClass, "Class2");
  2302. ProfileWriteString(dwKey, szFixModemClass, "2", TRUE);
  2303. break;
  2304. case MODEM_CLASS2_0 :
  2305. sprintf(szClass, "Class2_0");
  2306. ProfileWriteString(dwKey, szFixModemClass, "20", TRUE);
  2307. break;
  2308. default:
  2309. sprintf(szClass, "Class1");
  2310. }
  2311. ////// Modem Commands
  2312. if (pTG->TmpSettings.dwGot & fGOTCMD_Reset)
  2313. ProfileWriteString(dwKey, szResetCommand, pTG->TmpSettings.szReset, TRUE);
  2314. if (pTG->TmpSettings.dwGot & fGOTCMD_Setup)
  2315. ProfileWriteString(dwKey, szSetupCommand, pTG->TmpSettings.szSetup, TRUE);
  2316. if (pTG->TmpSettings.dwGot & fGOTCMD_PreExit)
  2317. ProfileWriteString(dwKey, szExitCommand , pTG->TmpSettings.szExit, TRUE);
  2318. if (pTG->TmpSettings.dwGot & fGOTCMD_PreDial)
  2319. ProfileWriteString(dwKey, szPreDialCommand , pTG->TmpSettings.szPreDial, TRUE);
  2320. if (pTG->TmpSettings.dwGot & fGOTCMD_PreAnswer)
  2321. ProfileWriteString(dwKey, szPreAnswerCommand, pTG->TmpSettings.szPreAnswer, TRUE);
  2322. //
  2323. // Adaptive Answer
  2324. //
  2325. if (pTG->AdaptiveAnswerEnable)
  2326. {
  2327. // create szClass key if it doesn't exist
  2328. sprintf(KeyName, "%s\\%s", pTG->FComModem.rgchKey, szClass);
  2329. dwKeyAdaptiveAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_CREATE | fREG_READ | fREG_WRITE);
  2330. if (dwKeyAdaptiveAnswer == 0)
  2331. {
  2332. DebugPrintEx(DEBUG_ERR,"couldn't open szClass.");
  2333. goto failure;
  2334. }
  2335. ProfileClose(dwKeyAdaptiveAnswer);
  2336. // create Class\AdaptiveAnswer key if it doesn't exist
  2337. sprintf(KeyName, "%s\\%s\\AdaptiveAnswer", pTG->FComModem.rgchKey, szClass);
  2338. dwKeyAdaptiveAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_CREATE | fREG_READ | fREG_WRITE);
  2339. if (dwKeyAdaptiveAnswer == 0)
  2340. {
  2341. DebugPrintEx(DEBUG_ERR,"couldn't open AdaptiveAnswer.");
  2342. goto failure;
  2343. }
  2344. // create Class1\AdaptiveAnswer\Answer key if it doesn't exist
  2345. sprintf(KeyName, "%s\\%s\\AdaptiveAnswer\\AnswerCommand", pTG->FComModem.rgchKey ,szClass);
  2346. dwKeyAnswer = ProfileOpen(pTG->FComModem.dwProfileID, KeyName, fREG_CREATE | fREG_READ | fREG_WRITE);
  2347. if (dwKeyAnswer == 0)
  2348. {
  2349. DebugPrintEx(DEBUG_ERR,"couldn't open AdaptiveAnswer\\AnswerCommand .");
  2350. goto failure;
  2351. }
  2352. for (i=0; i<pTG->AnswerCommandNum; i++)
  2353. {
  2354. sprintf (KeyName, "%d", i+1);
  2355. ProfileWriteString (dwKeyAnswer, KeyName , pTG->AnswerCommand[i], TRUE );
  2356. MemFree( pTG->AnswerCommand[i]);
  2357. pTG->AnswerCommand[i] = NULL;
  2358. }
  2359. pTG->AnswerCommandNum = 0;
  2360. ProfileClose(dwKeyAnswer);
  2361. // store the rest of the AdaptiveAnswer values
  2362. if (pTG->ModemResponseFaxDetect)
  2363. {
  2364. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseFaxDetect, pTG->ModemResponseFaxDetect, FALSE);
  2365. MemFree( pTG->ModemResponseFaxDetect );
  2366. pTG->ModemResponseFaxDetect = NULL;
  2367. }
  2368. if (pTG->ModemResponseDataDetect)
  2369. {
  2370. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseDataDetect, pTG->ModemResponseDataDetect, FALSE);
  2371. MemFree (pTG->ModemResponseDataDetect);
  2372. pTG->ModemResponseDataDetect = NULL;
  2373. }
  2374. if (pTG->SerialSpeedFaxDetect)
  2375. {
  2376. sprintf (KeyName, "%d", pTG->SerialSpeedFaxDetect);
  2377. ProfileWriteString (dwKeyAdaptiveAnswer, szSerialSpeedFaxDetect, KeyName, FALSE);
  2378. }
  2379. if (pTG->SerialSpeedDataDetect)
  2380. {
  2381. sprintf (KeyName, "%d", pTG->SerialSpeedDataDetect);
  2382. ProfileWriteString (dwKeyAdaptiveAnswer, szSerialSpeedDataDetect, KeyName, FALSE);
  2383. }
  2384. if (pTG->HostCommandFaxDetect)
  2385. {
  2386. ProfileWriteString (dwKeyAdaptiveAnswer, szHostCommandFaxDetect, pTG->HostCommandFaxDetect, TRUE);
  2387. MemFree( pTG->HostCommandFaxDetect);
  2388. pTG->HostCommandFaxDetect = NULL;
  2389. }
  2390. if (pTG->HostCommandDataDetect)
  2391. {
  2392. ProfileWriteString (dwKeyAdaptiveAnswer, szHostCommandDataDetect, pTG->HostCommandDataDetect,TRUE);
  2393. MemFree( pTG->HostCommandDataDetect);
  2394. pTG->HostCommandDataDetect = NULL;
  2395. }
  2396. if (pTG->ModemResponseFaxConnect)
  2397. {
  2398. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseFaxConnect, pTG->ModemResponseFaxConnect, FALSE);
  2399. MemFree( pTG->ModemResponseFaxConnect);
  2400. pTG->ModemResponseFaxConnect = NULL;
  2401. }
  2402. if (pTG->ModemResponseDataConnect)
  2403. {
  2404. ProfileWriteString (dwKeyAdaptiveAnswer, szModemResponseDataConnect, pTG->ModemResponseDataConnect, FALSE);
  2405. MemFree(pTG->ModemResponseDataConnect);
  2406. pTG->ModemResponseDataConnect = NULL;
  2407. }
  2408. ProfileClose(dwKeyAdaptiveAnswer);
  2409. }
  2410. if (pTG->fEnableHardwareFlowControl)
  2411. {
  2412. ProfileWriteString (dwKey, szHardwareFlowControl, "1", FALSE);
  2413. }
  2414. //
  2415. // Serial Speed
  2416. //
  2417. if (pTG->SerialSpeedInitSet)
  2418. {
  2419. wsprintf(pTG->TmpSettings.szSmallTemp1, "%lu", (unsigned long) pTG->SerialSpeedInit);
  2420. ProfileWriteString(dwKey, szSerialSpeedInit, pTG->TmpSettings.szSmallTemp1, FALSE);
  2421. }
  2422. // Classes 2 and 2.0
  2423. SaveCl2Settings(pTG, dwKey);
  2424. if (dwKey)
  2425. ProfileClose(dwKey);
  2426. return TRUE;
  2427. failure:
  2428. if (dwKey)
  2429. ProfileClose(dwKey);
  2430. return FALSE;
  2431. }
  2432. BOOL imodem_alloc_tmp_strings(PThrdGlbl pTG)
  2433. {
  2434. WORD w;
  2435. LPSTR lpstr;
  2436. LPVOID lpv;
  2437. DEBUG_FUNCTION_NAME(("imodem_alloc_tmp_strings"));
  2438. w = TMPSTRINGBUFSIZE;
  2439. pTG->TmpSettings.hglb = (ULONG_PTR) MemAlloc(TMPSTRINGBUFSIZE);
  2440. if (!pTG->TmpSettings.hglb)
  2441. {
  2442. goto failure;
  2443. }
  2444. lpv = (LPVOID) (pTG->TmpSettings.hglb);
  2445. lpstr=(LPSTR)lpv;
  2446. if (!lpstr)
  2447. {
  2448. MemFree( (PVOID) pTG->TmpSettings.hglb);
  2449. pTG->TmpSettings.hglb=0;
  2450. goto failure;
  2451. }
  2452. pTG->TmpSettings.lpbBuf = (LPBYTE)lpstr;
  2453. _fmemset(lpstr, 0, TMPSTRINGBUFSIZE);
  2454. pTG->TmpSettings.szReset = lpstr; lpstr+=MAXCMDSIZE;
  2455. pTG->TmpSettings.szResetGenerated = lpstr; lpstr+=MAXCMDSIZE;
  2456. pTG->TmpSettings.szSetup = lpstr; lpstr+=MAXCMDSIZE;
  2457. pTG->TmpSettings.szSetupGenerated = lpstr; lpstr+=MAXCMDSIZE;
  2458. pTG->TmpSettings.szExit = lpstr; lpstr+=MAXCMDSIZE;
  2459. pTG->TmpSettings.szPreDial = lpstr; lpstr+=MAXCMDSIZE;
  2460. pTG->TmpSettings.szPreAnswer = lpstr; lpstr+=MAXCMDSIZE;
  2461. pTG->TmpSettings.szIDCmd = lpstr; lpstr+=MAXCMDSIZE;
  2462. pTG->TmpSettings.szID = lpstr; lpstr+=MAXIDSIZE;
  2463. pTG->TmpSettings.szResponseBuf = lpstr; lpstr+=RESPONSEBUFSIZE;
  2464. pTG->TmpSettings.szSmallTemp1 = lpstr; lpstr+=SMALLTEMPSIZE;
  2465. pTG->TmpSettings.szSmallTemp2 = lpstr; lpstr+=SMALLTEMPSIZE;
  2466. pTG->TmpSettings.dwGot=0;
  2467. if ( ((LPSTR)lpv+TMPSTRINGBUFSIZE) < lpstr)
  2468. {
  2469. MemFree( (PVOID) pTG->TmpSettings.hglb);
  2470. pTG->TmpSettings.hglb=0;
  2471. goto failure;
  2472. }
  2473. return TRUE;
  2474. failure:
  2475. DebugPrintEx(DEBUG_ERR,"MyAlloc/MyLock failed!");
  2476. return FALSE;
  2477. }
  2478. void imodem_free_tmp_strings(PThrdGlbl pTG)
  2479. {
  2480. if (pTG->TmpSettings.hglb)
  2481. {
  2482. MemFree( (PVOID) pTG->TmpSettings.hglb);
  2483. }
  2484. _fmemset(&pTG->TmpSettings, 0, sizeof(pTG->TmpSettings));
  2485. }
  2486. void imodem_clear_tmp_settings(PThrdGlbl pTG)
  2487. {
  2488. _fmemset(pTG->TmpSettings.lpMdmCaps, 0, sizeof(MODEMCAPS));
  2489. pTG->TmpSettings.dwGot=0;
  2490. pTG->TmpSettings.uDontPurge=0;
  2491. pTG->TmpSettings.dwSerialSpeed=0;
  2492. pTG->TmpSettings.dwFlags=0;
  2493. _fmemset(pTG->TmpSettings.lpbBuf, 0, TMPSTRINGBUFSIZE);
  2494. }
  2495. BOOL
  2496. imodem_list_get_str
  2497. (
  2498. PThrdGlbl pTG,
  2499. ULONG_PTR KeyList[10],
  2500. LPSTR lpszName,
  2501. LPSTR lpszCmdBuf,
  2502. UINT cbMax,
  2503. BOOL fCmd
  2504. )
  2505. {
  2506. int i;
  2507. int Num=0;
  2508. BOOL bRet=0;
  2509. for (i=0; i<10; i++)
  2510. {
  2511. if (KeyList[i] == 0)
  2512. {
  2513. Num = i-1;
  2514. break;
  2515. }
  2516. }
  2517. for (i=Num; i>=0; i--)
  2518. {
  2519. if ( bRet = imodem_get_str(pTG, KeyList[i], lpszName, lpszCmdBuf, cbMax, fCmd) )
  2520. {
  2521. return bRet;
  2522. }
  2523. }
  2524. return bRet;
  2525. }
  2526. BOOL imodem_get_str
  2527. (
  2528. PThrdGlbl pTG,
  2529. ULONG_PTR dwKey,
  2530. LPSTR lpszName,
  2531. LPSTR lpszCmdBuf,
  2532. UINT cbMax,
  2533. BOOL fCmd
  2534. )
  2535. {
  2536. UINT uLen2;
  2537. char *pc = "bogus";
  2538. *lpszCmdBuf=0;
  2539. uLen2 = ProfileGetString(dwKey, lpszName,pc, lpszCmdBuf, cbMax-1);
  2540. if (uLen2)
  2541. {
  2542. if (!_fstrcmp(lpszCmdBuf, pc))
  2543. {
  2544. *lpszCmdBuf=0; return FALSE;
  2545. }
  2546. if (fCmd)
  2547. EndWithCR(lpszCmdBuf, (USHORT)uLen2);
  2548. }
  2549. return TRUE;
  2550. }
  2551. BOOL iModemCopyOEMInfo(PThrdGlbl pTG)
  2552. {
  2553. return ProfileCopyTree( DEF_BASEKEY,
  2554. pTG->FComModem.rgchKey,
  2555. OEM_BASEKEY,
  2556. pTG->lpszUnimodemFaxKey);
  2557. }
  2558. #define MASKOFFV17 0x03
  2559. void SmashCapsAccordingToSettings(PThrdGlbl pTG)
  2560. {
  2561. // INI file has already been read.
  2562. DEBUG_FUNCTION_NAME(("SmashCapsAccordingToSettings"));
  2563. // If !fV17Enable then smash the V17 bits of the Capabilities
  2564. if(!pTG->Inst.ProtParams.fEnableV17Send)
  2565. {
  2566. DebugPrintEx(DEBUG_WRN,"Masking off V.17 send capabilities");
  2567. pTG->FComModem.CurrMdmCaps.uSendSpeeds &= MASKOFFV17;
  2568. }
  2569. if(!pTG->Inst.ProtParams.fEnableV17Recv)
  2570. {
  2571. DebugPrintEx(DEBUG_WRN,"Masking off V.17 receive capabilities");
  2572. pTG->FComModem.CurrMdmCaps.uRecvSpeeds &= MASKOFFV17;
  2573. }
  2574. //
  2575. // commented out RSL. We run at 19200. Nowhere in awmodem.inf have I seen FixSerialSpeed clause.
  2576. //
  2577. DebugPrintEx( DEBUG_MSG,
  2578. "uSendSpeeds=%x uRecvSpeeds=%x",
  2579. pTG->FComModem.CurrMdmCaps.uSendSpeeds,
  2580. pTG->FComModem.CurrMdmCaps.uRecvSpeeds);
  2581. }
  2582. int
  2583. SearchNewInfFile
  2584. (
  2585. PThrdGlbl pTG,
  2586. char *Key1,
  2587. char *Key2,
  2588. BOOL fRead
  2589. )
  2590. {
  2591. char szInfSection[] = "SecondKey=";
  2592. DWORD lenNewInf;
  2593. int RetCode = FALSE;
  2594. char Buffer[400]; // to hold lpToken=lpValue string
  2595. char *lpCurrent;
  2596. char *lpStartSection;
  2597. char *lpTmp;
  2598. char *lpToken;
  2599. char *lpValue;
  2600. ToCaps(Key1);
  2601. if (Key2)
  2602. {
  2603. ToCaps(Key2);
  2604. }
  2605. pTG->AnswerCommandNum = 0;
  2606. if ( ( lenNewInf = strlen(szAdaptiveInf) ) == 0 )
  2607. {
  2608. return FALSE;
  2609. }
  2610. //
  2611. // Loop thru all segments.
  2612. // Each segment starts with InfPath=
  2613. //
  2614. lpCurrent = szAdaptiveInf;
  2615. do
  2616. {
  2617. // find InfPath
  2618. lpStartSection = strstr (lpCurrent, szResponsesKeyName);
  2619. if (! lpStartSection)
  2620. {
  2621. goto exit;
  2622. }
  2623. lpTmp = strchr (lpStartSection, '\r' );
  2624. if (!lpTmp)
  2625. {
  2626. goto exit;
  2627. }
  2628. // compare Key1
  2629. if ( strlen(Key1) != (lpTmp - lpStartSection - strlen(szResponsesKeyName) ) )
  2630. {
  2631. lpCurrent = lpTmp;
  2632. continue;
  2633. }
  2634. if ( memcmp (lpStartSection+strlen(szResponsesKeyName),
  2635. Key1,
  2636. (ULONG)(lpTmp - lpStartSection - strlen(szResponsesKeyName) ) ) != 0 )
  2637. {
  2638. lpCurrent = lpTmp;
  2639. continue;
  2640. }
  2641. // find InfSection
  2642. lpCurrent = lpTmp;
  2643. if (Key2)
  2644. {
  2645. lpStartSection = strstr (lpCurrent, szInfSection);
  2646. if (! lpStartSection)
  2647. {
  2648. goto exit;
  2649. }
  2650. lpTmp = strchr (lpStartSection, '\r' );
  2651. if (!lpTmp)
  2652. {
  2653. goto exit;
  2654. }
  2655. // compare Key2
  2656. if ( strlen(Key2) != (lpTmp - lpStartSection - strlen(szInfSection) ) )
  2657. {
  2658. lpCurrent = lpTmp;
  2659. continue;
  2660. }
  2661. if ( memcmp (lpStartSection+strlen(szInfSection),
  2662. Key2,
  2663. (ULONG)(lpTmp - lpStartSection - strlen(szInfSection)) ) != 0 )
  2664. {
  2665. lpCurrent = lpTmp;
  2666. continue;
  2667. }
  2668. lpCurrent = lpTmp;
  2669. }
  2670. //
  2671. // both keys matched. Go get settings and return
  2672. //
  2673. do
  2674. {
  2675. lpCurrent = strchr (lpCurrent, '\r' );
  2676. if (!lpCurrent)
  2677. {
  2678. goto exit;
  2679. }
  2680. lpCurrent += 2;
  2681. // find next setting inside the matching section
  2682. lpToken = lpCurrent;
  2683. lpCurrent = strchr (lpCurrent, '=' );
  2684. if (!lpCurrent)
  2685. {
  2686. goto exit;
  2687. }
  2688. lpTmp = strchr (lpToken, '\r' );
  2689. if (!lpTmp)
  2690. {
  2691. goto exit;
  2692. }
  2693. if (lpCurrent > lpTmp)
  2694. {
  2695. // empty string
  2696. lpCurrent = lpTmp;
  2697. continue;
  2698. }
  2699. lpValue = ++lpCurrent;
  2700. lpTmp = strchr (lpValue, '\r' );
  2701. if (!lpTmp)
  2702. {
  2703. goto exit;
  2704. }
  2705. // we parsed the string. Now get it to the Buffer
  2706. if (lpTmp - lpToken > sizeof (Buffer) )
  2707. {
  2708. goto exit;
  2709. }
  2710. memcpy(Buffer, lpToken, (ULONG)(lpTmp - lpToken));
  2711. Buffer[lpValue -lpToken - 1] = 0;
  2712. Buffer[lpTmp - lpToken] = 0;
  2713. lpValue = &Buffer[lpValue - lpToken];
  2714. lpToken = Buffer;
  2715. pTG->fAdaptiveRecordFound = 1;
  2716. if ( my_strcmp(lpToken, szAdaptiveAnswerEnable) )
  2717. {
  2718. pTG->AdaptiveAnswerEnable = atoi (lpValue);
  2719. }
  2720. else if ( my_strcmp(lpToken, szAdaptiveRecordUnique) )
  2721. {
  2722. pTG->fAdaptiveRecordUnique = atoi (lpValue);
  2723. }
  2724. else if ( my_strcmp(lpToken, szAdaptiveCodeId) )
  2725. {
  2726. pTG->AdaptiveCodeId = atoi (lpValue);
  2727. if ( ! fRead )
  2728. {
  2729. goto exit;
  2730. }
  2731. }
  2732. else if ( my_strcmp(lpToken, szFaxClass) )
  2733. {
  2734. ;
  2735. }
  2736. else if ( my_strcmp(lpToken, szHardwareFlowControl) )
  2737. {
  2738. pTG->fEnableHardwareFlowControl = atoi (lpValue);
  2739. }
  2740. else if ( my_strcmp(lpToken, szSerialSpeedInit) )
  2741. {
  2742. pTG->SerialSpeedInit = (USHORT)atoi (lpValue);
  2743. pTG->SerialSpeedInitSet = 1;
  2744. }
  2745. else if ( my_strcmp(lpToken, szResetCommand) )
  2746. {
  2747. sprintf ( pTG->TmpSettings.szReset, "%s\r", lpValue);
  2748. pTG->TmpSettings.dwGot |= fGOTCMD_Reset;
  2749. }
  2750. else if ( my_strcmp(lpToken, szSetupCommand) )
  2751. {
  2752. sprintf ( pTG->TmpSettings.szSetup, "%s\r", lpValue);
  2753. pTG->TmpSettings.dwGot |= fGOTCMD_Setup;
  2754. }
  2755. else if ( my_strcmp(lpToken, szAnswerCommand) )
  2756. {
  2757. if (pTG->AnswerCommandNum >= MAX_ANSWER_COMMANDS)
  2758. {
  2759. goto exit;
  2760. }
  2761. if (NULL != (pTG->AnswerCommand[pTG->AnswerCommandNum] = MemAlloc( strlen(lpValue) + 1)))
  2762. {
  2763. strcpy ( pTG->AnswerCommand[pTG->AnswerCommandNum], lpValue);
  2764. pTG->AnswerCommandNum++;
  2765. }
  2766. else
  2767. {
  2768. goto bad_exit;
  2769. }
  2770. }
  2771. else if ( my_strcmp(lpToken, szModemResponseFaxDetect) )
  2772. {
  2773. if (NULL != (pTG->ModemResponseFaxDetect = MemAlloc( strlen(lpValue) + 1)))
  2774. strcpy ( pTG->ModemResponseFaxDetect, lpValue);
  2775. else
  2776. goto bad_exit;
  2777. }
  2778. else if ( my_strcmp(lpToken, szModemResponseDataDetect) )
  2779. {
  2780. if (NULL != (pTG->ModemResponseDataDetect = MemAlloc( strlen(lpValue) + 1)))
  2781. strcpy ( pTG->ModemResponseDataDetect, lpValue);
  2782. else
  2783. goto bad_exit;
  2784. }
  2785. else if ( my_strcmp(lpToken, szSerialSpeedFaxDetect) )
  2786. {
  2787. pTG->SerialSpeedFaxDetect = (USHORT)atoi (lpValue);
  2788. }
  2789. else if ( my_strcmp(lpToken, szSerialSpeedDataDetect) )
  2790. {
  2791. pTG->SerialSpeedDataDetect = (USHORT)atoi (lpValue);
  2792. }
  2793. else if ( my_strcmp(lpToken, szHostCommandFaxDetect) )
  2794. {
  2795. if (NULL != (pTG->HostCommandFaxDetect = MemAlloc( strlen(lpValue) + 1)))
  2796. strcpy ( pTG->HostCommandFaxDetect, lpValue);
  2797. else
  2798. goto bad_exit;
  2799. }
  2800. else if ( my_strcmp(lpToken, szHostCommandDataDetect) )
  2801. {
  2802. if (NULL != (pTG->HostCommandDataDetect = MemAlloc( strlen(lpValue) + 1)))
  2803. strcpy ( pTG->HostCommandDataDetect, lpValue);
  2804. else
  2805. goto bad_exit;
  2806. }
  2807. else if ( my_strcmp(lpToken, szModemResponseFaxConnect) )
  2808. {
  2809. if (NULL != (pTG->ModemResponseFaxConnect = MemAlloc( strlen(lpValue) + 1)))
  2810. strcpy ( pTG->ModemResponseFaxConnect, lpValue);
  2811. else
  2812. goto bad_exit;
  2813. }
  2814. else if ( my_strcmp(lpToken, szModemResponseDataConnect) )
  2815. {
  2816. if (NULL != (pTG->ModemResponseDataConnect = MemAlloc( strlen(lpValue) + 1)))
  2817. strcpy ( pTG->ModemResponseDataConnect, lpValue);
  2818. else
  2819. goto bad_exit;
  2820. }
  2821. else if ( my_strcmp(lpToken, szResponsesKeyName2) )
  2822. {
  2823. RetCode = TRUE;
  2824. goto exit;
  2825. }
  2826. }
  2827. while ( 1 ); // section loop
  2828. }
  2829. while ( 1 ); // file loop
  2830. return (FALSE);
  2831. bad_exit:
  2832. CleanModemInfStrings (pTG);
  2833. exit:
  2834. return (RetCode);
  2835. }
  2836. VOID
  2837. CleanModemInfStrings (
  2838. PThrdGlbl pTG
  2839. )
  2840. {
  2841. DWORD i;
  2842. for (i=0; i<pTG->AnswerCommandNum; i++) {
  2843. if (pTG->AnswerCommand[i]) {
  2844. MemFree( pTG->AnswerCommand[i]);
  2845. pTG->AnswerCommand[i] = NULL;
  2846. }
  2847. }
  2848. pTG->AnswerCommandNum = 0;
  2849. if (pTG->ModemResponseFaxDetect) {
  2850. MemFree( pTG->ModemResponseFaxDetect );
  2851. pTG->ModemResponseFaxDetect = NULL;
  2852. }
  2853. if (pTG->ModemResponseDataDetect) {
  2854. MemFree (pTG->ModemResponseDataDetect);
  2855. pTG->ModemResponseDataDetect = NULL;
  2856. }
  2857. if (pTG->HostCommandFaxDetect) {
  2858. MemFree( pTG->HostCommandFaxDetect);
  2859. pTG->HostCommandFaxDetect = NULL;
  2860. }
  2861. if (pTG->HostCommandDataDetect) {
  2862. MemFree( pTG->HostCommandDataDetect);
  2863. pTG->HostCommandDataDetect = NULL;
  2864. }
  2865. if (pTG->ModemResponseFaxConnect) {
  2866. MemFree( pTG->ModemResponseFaxConnect);
  2867. pTG->ModemResponseFaxConnect = NULL;
  2868. }
  2869. if (pTG->ModemResponseDataConnect) {
  2870. MemFree(pTG->ModemResponseDataConnect);
  2871. pTG->ModemResponseDataConnect = NULL;
  2872. }
  2873. }