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.

1582 lines
51 KiB

  1. /*****************************************************************************
  2. ** Microsoft RAS Device INF Library wrapper **
  3. ** Copyright (C) 1992-93 Microsft Corporation. All rights reserved. **
  4. ** **
  5. ** File Name : msxwrap.c **
  6. ** **
  7. ** Revision History : **
  8. ** July 23, 1992 David Kays Created **
  9. ** Feb 22, 1993 Perryh Hannah Changed static routines to global to **
  10. ** ease degugging. **
  11. ** **
  12. ** Description : **
  13. ** RAS Device INF File Library wrapper above RASFILE Library for **
  14. ** modem/X.25/switch DLL (RASMXS). **
  15. *****************************************************************************/
  16. #define _CTYPE_DISABLE_MACROS
  17. #include <stddef.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include <windef.h>
  22. #include <winnt.h>
  23. #include <wtypes.h>
  24. #include "rasfile.h"
  25. #include "rasman.h" // RASMAN_DEVICEINFO, RAS_PARAMS struct, etc.
  26. #include "raserror.h" // SUCCESS & ERROR_BUFFER_TOO_SMALL
  27. #include "rasmxs.h" // Public rasmxs DLL error messages
  28. #include "mxsint.h" // Internal rasmxs DLL error messages
  29. #include "wrapint.h"
  30. #include "mxswrap.h"
  31. // local
  32. BOOL rasDevGroupFunc( LPTSTR );
  33. BOOL rasDevIsDecimalMacro ( LPTSTR );
  34. void rasDevGetMacroValue ( LPTSTR *, DWORD *, LPTSTR );
  35. void rasDevGetDecimalMacroValue ( LPTSTR *, DWORD *, LPTSTR );
  36. BOOL rasDevExpandMacros( LPTSTR, LPTSTR, DWORD *, BYTE,
  37. MACROXLATIONTABLE *);
  38. BOOL rasDevLookupMacro( LPTSTR, LPTSTR *, MACROXLATIONTABLE *);
  39. DWORD rasDevMacroInsert( MACRO *, WORD, MACROXLATIONTABLE *);
  40. void rasDevExtractKey ( LPTSTR , LPTSTR );
  41. void rasDevExtractValue ( LPTSTR , LPTSTR, DWORD, HRASFILE );
  42. void rasDevSortParams( LPTSTR *, DWORD );
  43. void rasDevCheckParams( LPTSTR *, DWORD *);
  44. void rasDevCheckMacros( LPTSTR *, LPTSTR *, DWORD *);
  45. BYTE ctox( char );
  46. void GetMem(DWORD dSize, BYTE **ppMem);
  47. /*
  48. * RasDevEnumDevices :
  49. * Returns in pBuffer an array of RASMAN_DEVICE structures which contain
  50. * all the devices in the INF file (i.e. all header names).
  51. *
  52. * Arguments :
  53. * lpszFileName (IN) - File path name of device file
  54. * pNumEntries (OUT) - Number of devices found in the INF file
  55. * pBuffer (OUT) - Buffer to contain the RASMAN_DEVICE structures
  56. * pwSize (INOUT) - Size of pBuffer, this parameter filled with
  57. * the needed size of pBuffer if too small
  58. *
  59. * Return Value :
  60. * ERROR_BUFFER_TOO_SMALL if pBuffer not big enough to hold all of the
  61. * RASMAN_DEVICE structs, SUCCESS otherwise.
  62. */
  63. DWORD APIENTRY
  64. RasDevEnumDevices( PTCH lpszFileName, DWORD *pNumEntries,
  65. BYTE *pBuffer, DWORD *pdwSize )
  66. {
  67. HRASFILE hFile;
  68. RASMAN_DEVICE DeviceName;
  69. DWORD dwCurSize;
  70. if ( (hFile = RasfileLoad(lpszFileName,RFM_ENUMSECTIONS,NULL,NULL)) == -1 )
  71. return ERROR_FILE_COULD_NOT_BE_OPENED;
  72. *pNumEntries = 0;
  73. if ( ! RasfileFindFirstLine(hFile,RFL_SECTION,RFS_FILE) ) {
  74. *pBuffer = '\0';
  75. *pdwSize = 0;
  76. RasfileClose(hFile);
  77. return SUCCESS;
  78. }
  79. // copy RASMAN_DEVICE structs
  80. dwCurSize = 0;
  81. do {
  82. // get the section name
  83. RasfileGetSectionName(hFile,(LPTSTR) &DeviceName);
  84. // ignore the Modem Responses section
  85. if ( ! _stricmp(RESPONSES_SECTION_NAME,(LPTSTR) &DeviceName) )
  86. continue;
  87. dwCurSize += sizeof(RASMAN_DEVICE);
  88. // if current size exceeds the size of the buffer then just
  89. // continue counting the size needed
  90. if ( dwCurSize > *pdwSize )
  91. continue;
  92. strcpy(pBuffer,(LPTSTR) &DeviceName);
  93. pBuffer += sizeof(RASMAN_DEVICE);
  94. (*pNumEntries)++;
  95. } while ( RasfileFindNextLine(hFile,RFL_SECTION,RFS_FILE) );
  96. RasfileClose(hFile);
  97. if ( dwCurSize > *pdwSize ) {
  98. *pdwSize = dwCurSize;
  99. return ERROR_BUFFER_TOO_SMALL;
  100. }
  101. else
  102. *pdwSize = dwCurSize;
  103. return SUCCESS;
  104. }
  105. /*
  106. * RasDevOpen :
  107. * Open an INF file for use by the device DLL.
  108. *
  109. * Arguments :
  110. * lpszFileName (IN) - File path name of device file
  111. * lpszSectionName (IN) - Section of device file to be loaded (by Rasfile)
  112. * hFile (OUT) - File handle obtained from RasfileLoad()
  113. *
  114. * Return Value :
  115. * ERROR_FILE_COULD_NOT_BE_OPENED if the file could not be found or opened.
  116. * ERROR_DEVICENAME_NOT_FOUND if the section name was not found in the
  117. * INF file.
  118. * ERROR_DEVICENAME_TOO_LONG if the section name is too long.
  119. * SUCCESS otherwise.
  120. */
  121. DWORD APIENTRY
  122. RasDevOpen( PTCH lpszFileName, PTCH lpszSectionName, HRASFILE *hFile )
  123. {
  124. HRASFILE hRasfile;
  125. if ( strlen(lpszSectionName) > MAX_DEVICE_NAME )
  126. return ERROR_DEVICENAME_TOO_LONG;
  127. // send RasfileLoad() the rasDevGroupFunc() to identify command lines
  128. // as group headers
  129. if ( (hRasfile = RasfileLoad(lpszFileName,RFM_READONLY,
  130. lpszSectionName,rasDevGroupFunc)) == -1 )
  131. return ERROR_FILE_COULD_NOT_BE_OPENED;
  132. // if there is no section header loaded then the device name is invalid
  133. if ( ! RasfileFindFirstLine(hRasfile,RFL_SECTION,RFS_FILE) ) {
  134. RasfileClose(hRasfile);
  135. return ERROR_DEVICENAME_NOT_FOUND;
  136. }
  137. // check if this section has an ALIAS
  138. // current Rasfile line is the section header
  139. if ( RasfileFindNextKeyLine(hRasfile,"ALIAS",RFS_SECTION) ) {
  140. // TCHAR szSection[MAX_DEVICE_NAME + 1];
  141. TCHAR *pszSection = NULL;
  142. pszSection = malloc(RAS_MAXLINEBUFLEN);
  143. if(NULL == pszSection)
  144. {
  145. return E_OUTOFMEMORY;
  146. }
  147. ZeroMemory(pszSection, RAS_MAXLINEBUFLEN);
  148. RasfileGetKeyValueFields(hRasfile,NULL,pszSection);
  149. RasfileClose(hRasfile);
  150. if ( (hRasfile = RasfileLoad(lpszFileName,RFM_READONLY,
  151. pszSection,rasDevGroupFunc)) == -1 )
  152. {
  153. free(pszSection);
  154. return ERROR_FILE_COULD_NOT_BE_OPENED;
  155. }
  156. free(pszSection);
  157. if ( ! RasfileFindFirstLine(hRasfile,RFL_SECTION,RFS_FILE) ) {
  158. RasfileClose(hRasfile);
  159. return ERROR_DEVICENAME_NOT_FOUND;
  160. }
  161. }
  162. // set the Rasfile current line to the first keyvalue line
  163. RasfileFindFirstLine(hRasfile,RFL_KEYVALUE,RFS_SECTION);
  164. *hFile = hRasfile;
  165. return SUCCESS;
  166. }
  167. /*
  168. * RasDevClose :
  169. * Close an INF file used by the device DLL.
  170. *
  171. * Arguments :
  172. * hFile (IN) - the Rasfile handle of the file to close
  173. *
  174. * Return Value :
  175. * ERROR_INVALID_HANDLE if hFile is invalid, SUCCESS otherwise.
  176. */
  177. void APIENTRY
  178. RasDevClose( HRASFILE hFile )
  179. {
  180. RasfileClose(hFile);
  181. }
  182. /*
  183. * RasDevGetParams :
  184. * Returns in pBuffer a RASMAN_DEVICEINFO structure which contains all of the
  185. * keyword=value pairs between the top of the section loaded and the
  186. * first command.
  187. *
  188. * Assumptions:
  189. * All strings read from INF files are zero terminated.
  190. *
  191. * Arguments :
  192. * hFile (IN) - the Rasfile handle of the opened INF file
  193. * pBuffer (OUT) - the buffer to hold the RASMAN_DEVICEINFO structure
  194. * pdSize (INOUT) - the size of pBuffer, this is filled in with the needed
  195. * buffer size to hold the RASMAN_DEVICEINFO struct if
  196. * pBuffer is too small
  197. *
  198. * Return Value :
  199. * ERROR_BUFFER_TOO_SMALL if pBuffer is too small to contain the
  200. * RASMAN_DEVICEINFO structure, SUCCESS otherwise.
  201. */
  202. DWORD APIENTRY
  203. RasDevGetParams( HRASFILE hFile, BYTE *pBuffer, DWORD *pdSize )
  204. {
  205. RASMAN_DEVICEINFO *pDeviceInfo;
  206. DWORD dParams, dCurrentSize, i, dValueLen;
  207. LPTSTR *alpszLines, *alpszLinesSave, *lppszLine, *alpszMallocedLines;
  208. BOOL bBufferTooSmall = FALSE;
  209. TCHAR szString[RAS_MAXLINEBUFLEN];
  210. if ( ! RasfileFindFirstLine(hFile,RFL_KEYVALUE,RFS_SECTION) ) {
  211. if (*pdSize >= sizeof(DWORD)) {
  212. *((DWORD *)pBuffer) = 0;
  213. *pdSize = sizeof(DWORD);
  214. return SUCCESS;
  215. }
  216. else {
  217. *pdSize = sizeof(DWORD);
  218. return ERROR_BUFFER_TOO_SMALL;
  219. }
  220. }
  221. // count the number of keyvalue lines between the top of section and
  222. // the first command, and the number of bytes to hold all of the lines
  223. dParams = 0;
  224. do {
  225. if ( RasfileGetLineType(hFile) & RFL_GROUP )
  226. break;
  227. dParams++;
  228. } while ( RasfileFindNextLine(hFile,RFL_KEYVALUE,RFS_SECTION) );
  229. RasfileFindFirstLine(hFile,RFL_KEYVALUE,RFS_SECTION);
  230. // malloc enough for two times as many lines as currently exist
  231. lppszLine = malloc(2 * dParams * sizeof(LPTSTR));
  232. alpszMallocedLines = malloc(dParams * sizeof(LPTSTR));
  233. if( (NULL == lppszLine)
  234. || (NULL == alpszMallocedLines))
  235. {
  236. DWORD retcode = GetLastError();
  237. if(NULL != lppszLine)
  238. {
  239. free(lppszLine);
  240. }
  241. if(NULL != alpszMallocedLines)
  242. {
  243. free(alpszMallocedLines);
  244. }
  245. return retcode;
  246. }
  247. alpszLines =lppszLine;
  248. // record all Rasfile keyvalue lines until a group header or end of
  249. // section is found
  250. do {
  251. if ( RasfileGetLineType(hFile) & RFL_GROUP )
  252. break;
  253. *lppszLine++ = (LPTSTR)RasfileGetLine(hFile);
  254. } while ( RasfileFindNextLine(hFile,RFL_KEYVALUE,RFS_SECTION) );
  255. // sort the lines by key
  256. rasDevSortParams( alpszLines, dParams );
  257. // check for duplicate keys and remove any that are found
  258. rasDevCheckParams( alpszLines, &dParams );
  259. // insert missing _ON or _OFF macros into the list
  260. rasDevCheckMacros( alpszLines, alpszMallocedLines, &dParams );
  261. // check if given buffer is large enough
  262. dCurrentSize = sizeof(RASMAN_DEVICEINFO)
  263. + ((dParams - 1) * sizeof(RAS_PARAMS));
  264. if ( (NULL == pBuffer)
  265. || (dCurrentSize > *pdSize )) {
  266. *pdSize = dCurrentSize;
  267. lppszLine = alpszMallocedLines;
  268. while ( *lppszLine != NULL )
  269. free(*lppszLine++);
  270. free(alpszMallocedLines);
  271. free(alpszLines);
  272. return ERROR_BUFFER_TOO_SMALL;
  273. }
  274. // fill in pBuffer with RASMAN_DEVICEINFO struct
  275. pDeviceInfo = (RASMAN_DEVICEINFO *) pBuffer;
  276. pDeviceInfo->DI_NumOfParams = (WORD) dParams;
  277. for ( i = 0, alpszLinesSave = alpszLines; i < dParams; i++, alpszLines++) {
  278. RAS_PARAMS *pParam;
  279. pParam = &(pDeviceInfo->DI_Params[i]);
  280. if (!bBufferTooSmall) {
  281. // set the Type and Attributes field
  282. pParam->P_Type = String;
  283. if ( strcspn(*alpszLines,LMS) < strcspn(*alpszLines,"=") )
  284. pParam->P_Attributes = 0;
  285. else
  286. pParam->P_Attributes = ATTRIB_VARIABLE;
  287. // get the key
  288. rasDevExtractKey(*alpszLines,pParam->P_Key);
  289. // if there are continuation lines for this keyword=value pair,
  290. // then set Rasfile line to the proper line
  291. if ( strcspn(*alpszLines,"\\") < strlen(*alpszLines) ) {
  292. TCHAR szFullKey[MAX_PARAM_KEY_SIZE];
  293. if ( ! pParam->P_Attributes ) {
  294. strcpy(szFullKey,LMS);
  295. strcat(szFullKey,pParam->P_Key);
  296. strcat(szFullKey,RMS);
  297. }
  298. else
  299. strcpy(szFullKey,pParam->P_Key);
  300. // find the last occurence of this key
  301. RasfileFindFirstLine(hFile,RFL_KEYVALUE,RFS_SECTION);
  302. while ( RasfileFindNextKeyLine(hFile,szFullKey,RFS_SECTION) )
  303. ;
  304. }
  305. }
  306. // get the value string
  307. rasDevExtractValue(*alpszLines,
  308. szString,
  309. sizeof(szString),
  310. hFile);
  311. dValueLen = strlen(szString);
  312. pParam->P_Value.String.Length = dValueLen;
  313. pParam->P_Value.String.Data = malloc(dValueLen + 1);
  314. if(NULL != pParam->P_Value.String.Data)
  315. {
  316. strcpy(pParam->P_Value.String.Data, szString);
  317. }
  318. }
  319. // free up all mallocs
  320. lppszLine = alpszMallocedLines;
  321. while ( *lppszLine != NULL )
  322. free(*lppszLine++);
  323. free(alpszMallocedLines);
  324. free(alpszLinesSave);
  325. return SUCCESS;
  326. }
  327. /*
  328. * RasDevGetCommand :
  329. * Returns the next command line of the given type and advances
  330. * the Rasfile file pointer to the first line following this command
  331. * line.
  332. *
  333. * Arguments :
  334. * hFile (IN) - the Rasfile file handle for the INF file
  335. * pszCmdTypeSuffix (IN) - the type of command line to search for :
  336. * GENERIC, INIT, DIAL, or LISTEN.
  337. * pMacroXlations (IN) - the Macro Translation table used to expand
  338. * all macros in the command line
  339. * lpsCommand (OUT) - buffer to hold the value string of the found
  340. * command line
  341. * pdwCmdLen (OUT) - length of output string with expanded macros
  342. *
  343. * Return Value :
  344. * ERROR_END_OF_SECTION if no command lines of the given type could
  345. * be found.
  346. * ERROR_MACRO_NOT_DEFINED if no entry in the given Macro Translation table
  347. * for a macro found in the command line could be found.
  348. * SUCCESS otherwise.
  349. */
  350. DWORD APIENTRY
  351. RasDevGetCommand( HRASFILE hFile, PTCH pszCmdTypeSuffix,
  352. MACROXLATIONTABLE *pMacroXlations, PTCH lpsCommand,
  353. DWORD *pdwCmdLen )
  354. {
  355. TCHAR szLineKey[MAX_PARAM_KEY_SIZE], sCommand[MAX_PARAM_KEY_SIZE];
  356. TCHAR szValue[RAS_MAXLINEBUFLEN];
  357. TCHAR sCommandValue[2*MAX_CMD_BUF_LEN];// WARNING : if we ever
  358. // get a command line > this
  359. // size msxwrap could bomb!
  360. LPTSTR lpszLine;
  361. if ( ! (RasfileGetLineType(hFile) & RFL_GROUP) ) {
  362. if ( ! RasfileFindNextLine(hFile,RFL_GROUP,RFS_SECTION) )
  363. return ERROR_END_OF_SECTION;
  364. }
  365. else if ( RasfileGetLineMark(hFile) == EOS_COOKIE ) {
  366. RasfilePutLineMark(hFile,0);
  367. return ERROR_END_OF_SECTION;
  368. }
  369. strncpy(sCommand,"command",MAX_PARAM_KEY_SIZE-1);
  370. strncat(sCommand,pszCmdTypeSuffix,MAX_PARAM_KEY_SIZE-sizeof("command")-1);
  371. for ( ;; ) {
  372. lpszLine = (LPTSTR) RasfileGetLine(hFile);
  373. if(NULL == lpszLine)
  374. {
  375. break;
  376. }
  377. rasDevExtractKey(lpszLine,szLineKey);
  378. if ( ! _stricmp(sCommand,szLineKey) ) {
  379. // get the value string
  380. lpszLine = (LPTSTR) RasfileGetLine(hFile);
  381. if(!lpszLine)
  382. return ERROR_END_OF_SECTION;
  383. rasDevExtractValue((LPTSTR)lpszLine,szValue,
  384. RAS_MAXLINEBUFLEN,hFile);
  385. // expand all macros in the value string
  386. if ( ! rasDevExpandMacros(szValue, sCommandValue, pdwCmdLen,
  387. EXPAND_ALL, pMacroXlations) )
  388. return ERROR_MACRO_NOT_DEFINED;
  389. if ( *pdwCmdLen > MAX_CMD_BUF_LEN )
  390. return ERROR_CMD_TOO_LONG;
  391. else
  392. memcpy(lpsCommand, sCommandValue, *pdwCmdLen);
  393. break;
  394. }
  395. if ( ! RasfileFindNextLine(hFile,RFL_GROUP,RFS_SECTION) )
  396. return ERROR_END_OF_SECTION;
  397. }
  398. // advance to the first response following the command or
  399. // to the next command line; if no such line exists mark the
  400. // current line as the end of the section
  401. if ( ! RasfileFindNextLine(hFile,RFL_ANYACTIVE,RFS_SECTION) )
  402. RasfilePutLineMark(hFile,EOS_COOKIE);
  403. return SUCCESS;
  404. }
  405. /*
  406. * RasDevResetCommand :
  407. * Moves the Rasfile file pointer to the first command of any type
  408. * in the loaded section.
  409. *
  410. * Arguments :
  411. * hFile (IN) - the Rasfile handle to the loaded file
  412. *
  413. * Return Value :
  414. * ERROR_NO_COMMAND_FOUND if no command line could be found,
  415. * SUCCESS otherwise.
  416. */
  417. DWORD APIENTRY
  418. RasDevResetCommand( HRASFILE hFile )
  419. {
  420. if ( ! RasfileFindFirstLine(hFile,RFL_GROUP,RFS_SECTION) )
  421. return ERROR_NO_COMMAND_FOUND;
  422. else
  423. return SUCCESS;
  424. }
  425. /*
  426. * RasDevCheckResponse :
  427. * Returns the keyword found in the line whose value string matches
  428. * the string in lpszReceived. Any macros other than fixed macros
  429. * which are found in the received string have their values copied
  430. * into the Macro Translation table.
  431. * All lines in a Command-Response Set are checked.
  432. *
  433. * Arguments :
  434. * hFile (IN) - the Rasfile handle to the loaded file
  435. * lpszReceived (IN) - the string received from the modem or X25 net
  436. * dReceivedLength (IN) - length of the received string
  437. * pMacroXlations (INOUT) - the Macro Translation table
  438. * lpszResponse (OUT) - buffer to copy the found keyword into
  439. *
  440. * Return Value :
  441. * ERROR_PARTIAL_RESPONSE if a line is matched up to the APPEND_MACRO.
  442. * ERROR_MACRO_NOT_DEFINED if a value for "carrierbaud", "connectbaud",
  443. * or "diagnotics" is found in the received string, but could
  444. * not be found in the given Macro Translation table.
  445. * ERROR_UNRECOGNIZED_RESPONSE if no matching reponse could be
  446. * found.
  447. * ERROR_NO_REPSONSES if when called, the Rasfile current line is a
  448. * command, section header, or is invalid.
  449. * SUCCESS otherwise.
  450. */
  451. DWORD APIENTRY
  452. RasDevCheckResponse( HRASFILE hFile, PTCH lpsReceived, DWORD dReceivedLength,
  453. MACROXLATIONTABLE *pMacroXlations, PTCH lpszResponse )
  454. {
  455. LPTSTR lpszValue, lpsRec, lpszResponseLine;
  456. TCHAR szValueString[RAS_MAXLINEBUFLEN], szValue[RAS_MAXLINEBUFLEN];
  457. MACRO aszMacros[10];
  458. DWORD dwRC, dRecLength, dwValueLen;
  459. WORD wMacros;
  460. BYTE bMatch;
  461. // find the nearest previous COMMAND line (Modem section) or
  462. // the section header (Modem Responses section)
  463. if ( RasfileGetLineMark(hFile) != EOS_COOKIE ) {
  464. RasfileFindPrevLine(hFile,RFL_ANYHEADER,RFS_SECTION);
  465. // set Rasfile line to the first keyvalue line in the response set
  466. RasfileFindNextLine(hFile,RFL_KEYVALUE,RFS_SECTION);
  467. }
  468. // else this line is a COMMAND line and the last line of the section
  469. // and ERROR_NO_RESPONSES will be returned
  470. if ( RasfileGetLine(hFile) == NULL ||
  471. RasfileGetLineType(hFile) & RFL_ANYHEADER )
  472. return ERROR_NO_RESPONSES;
  473. for ( ;; ) {
  474. lpszResponseLine = (LPTSTR)RasfileGetLine(hFile);
  475. if(NULL == lpszResponseLine)
  476. {
  477. return ERROR_NO_RESPONSES;
  478. }
  479. rasDevExtractValue(lpszResponseLine,szValueString,
  480. RAS_MAXLINEBUFLEN,hFile);
  481. // expand <cr> and <lf> macros only
  482. //*** Warning: this could expand line beyond array size!
  483. if ( ! rasDevExpandMacros(szValueString, szValue, &dwValueLen,
  484. EXPAND_FIXED_ONLY, NULL) )
  485. return ERROR_MACRO_NOT_DEFINED;
  486. lpsRec = lpsReceived;
  487. dRecLength = dReceivedLength;
  488. bMatch = 0;
  489. wMacros = 0;
  490. for ( lpszValue = szValue; *lpszValue != '\0' && dRecLength > 0; ) {
  491. // check for a macro
  492. if ( *lpszValue == LMSCH ) {
  493. // check for <<
  494. if (*(lpszValue + 1) == LMSCH) {
  495. if (*lpsRec == LMSCH) {
  496. lpszValue +=2;
  497. lpsRec++;
  498. dRecLength--;
  499. }
  500. else
  501. break; // fond a mismatch
  502. }
  503. // check for <append> macro and simply advance past it
  504. else if ( ! _strnicmp(lpszValue,APPEND_MACRO,
  505. strlen(APPEND_MACRO)) )
  506. lpszValue += strlen(APPEND_MACRO);
  507. // check for <ignore> macro
  508. else if ( ! _strnicmp(lpszValue,IGNORE_MACRO,
  509. strlen(IGNORE_MACRO)) ) {
  510. bMatch = FULL_MATCH;
  511. break;
  512. }
  513. // check for <match> macro
  514. else if ( ! _strnicmp(lpszValue,MATCH_MACRO,
  515. strlen(MATCH_MACRO)) ) {
  516. TCHAR szSubString[RAS_MAXLINEBUFLEN];
  517. memset(szSubString,0,RAS_MAXLINEBUFLEN);
  518. // advance value string to first char in match string
  519. lpszValue += strcspn(lpszValue,"\"") + 1;
  520. // extract match string
  521. strncpy(szSubString,lpszValue,strcspn(lpszValue,"\""));
  522. if ( RasDevSubStr(lpsRec,
  523. dRecLength,
  524. szSubString,
  525. strlen(szSubString)) != NULL ) {
  526. rasDevExtractKey(lpszResponseLine,lpszResponse);
  527. return SUCCESS;
  528. }
  529. else
  530. break; // value string does not match
  531. }
  532. // check for hex macro
  533. else if ( (lpszValue[1] == 'h' || lpszValue[1] == 'H') &&
  534. isxdigit(lpszValue[2]) && isxdigit(lpszValue[3]) &&
  535. lpszValue[4] == RMSCH ) {
  536. char c;
  537. c = (char) (ctox(lpszValue[2]) * 0x10 + ctox(lpszValue[3]));
  538. if ( c == *lpsRec++ ) {
  539. lpszValue += 5; // '<', 'h', two hex digits, and '>'
  540. dRecLength--;
  541. continue;
  542. }
  543. else // does not match
  544. break;
  545. }
  546. // check for wildcard character
  547. else if ( ! _strnicmp(lpszValue,WILDCARD_MACRO,
  548. strlen(WILDCARD_MACRO)) ) {
  549. lpszValue += strlen(WILDCARD_MACRO);
  550. lpsRec++; // advance Receive string one character
  551. dRecLength--;
  552. }
  553. else { // get macro name and value
  554. memset(aszMacros[wMacros].MacroName,0,MAX_PARAM_KEY_SIZE);
  555. // copy macro name
  556. strncpy(aszMacros[wMacros].MacroName, lpszValue + 1,
  557. strcspn(lpszValue,RMS) - 1);
  558. // advance the value string over the macro
  559. lpszValue += strcspn(lpszValue,RMS) + 1 /* past RMS */;
  560. // get macro value
  561. if (rasDevIsDecimalMacro(aszMacros[wMacros].MacroName))
  562. rasDevGetDecimalMacroValue(&lpsRec, &dRecLength,
  563. aszMacros[wMacros++].MacroValue);
  564. else
  565. rasDevGetMacroValue(&lpsRec, &dRecLength,
  566. aszMacros[wMacros++].MacroValue);
  567. }
  568. }
  569. else if ( *lpszValue == *lpsRec ) {
  570. if (*lpszValue == RMSCH && *(lpszValue + 1) == RMSCH)
  571. lpszValue++;
  572. lpszValue++;
  573. lpsRec++;
  574. dRecLength--;
  575. continue;
  576. }
  577. else // found a mismatch
  578. break;
  579. } // for
  580. // If we already have a match break out pf outer loop now
  581. if (bMatch != 0)
  582. break;
  583. // full match. When there is trailing line noise dRecLength will not
  584. // be zero, so check for full match aganist length of expected
  585. // response. Also make sure expected response is not empty.
  586. if ( *lpszValue == '\0' && lpszValue != szValue) {
  587. bMatch |= FULL_MATCH;
  588. break;
  589. }
  590. // partial match
  591. else if ( dRecLength == 0 &&
  592. ! _strnicmp(lpszValue,APPEND_MACRO,strlen(APPEND_MACRO)) ) {
  593. bMatch |= PARTIAL_MATCH;
  594. break;
  595. }
  596. if ( ! RasfileFindNextLine(hFile,RFL_KEYVALUE,RFS_SECTION) )
  597. return ERROR_UNRECOGNIZED_RESPONSE;
  598. if ( RasfileGetLineType(hFile) & RFL_GROUP )
  599. return ERROR_UNRECOGNIZED_RESPONSE;
  600. } // for
  601. // sanity check
  602. if ( ! (bMatch & (FULL_MATCH | PARTIAL_MATCH)) )
  603. return ERROR_UNRECOGNIZED_RESPONSE;
  604. // only get this far if a full or partial match was made
  605. // insert any macro values found in the received string
  606. // into the macro translation table
  607. if ((dwRC = rasDevMacroInsert(aszMacros,wMacros,pMacroXlations)) != SUCCESS)
  608. return(dwRC);
  609. // finally, copy the keyword string into lpszResponse string
  610. rasDevExtractKey(lpszResponseLine,lpszResponse);
  611. return ( bMatch & FULL_MATCH ) ? SUCCESS : ERROR_PARTIAL_RESPONSE;
  612. }
  613. /*
  614. * RasDevResponseExpected :
  615. * Checks the INF for presence of reponses to the current command.
  616. * If the key work "NoResponse" is found on the current line the
  617. * function returns FALSE. Otherwise modems always expect responses.
  618. *
  619. * Arguments :
  620. * hFile (IN) - Rasfile file handle for the INF file.
  621. * eDevType (IN) - The type of the device. (Modem, PAD, or Switch)
  622. *
  623. * Return Value :
  624. * FALSE if the current Rasfile line points to a command line or the
  625. * current line starts with "NoResponse", TRUE otherwise. Except
  626. * modems always return TRUE unless "NoResponse" key word is found.
  627. * (See code.)
  628. */
  629. BOOL APIENTRY
  630. RasDevResponseExpected( HRASFILE hFile, DEVICETYPE eDevType )
  631. {
  632. TCHAR szLine[RAS_MAXLINEBUFLEN];
  633. szLine[0] = TEXT('\0');
  634. RasfileGetLineText( hFile, szLine );
  635. if ( _strnicmp(szLine, MXS_NORESPONSE, strlen(MXS_NORESPONSE)) == 0 )
  636. return( FALSE );
  637. if (eDevType == DT_MODEM)
  638. return( TRUE );
  639. if ( RasfileGetLineType(hFile) & RFL_ANYHEADER )
  640. return( FALSE );
  641. else
  642. return( TRUE );
  643. }
  644. /*
  645. * RasDevEchoExpected :
  646. * Checks the current line of the INF file for the keyword NoEcho.
  647. * If found the function returns FALSE. Otherwise, it returns TRUE.
  648. *
  649. * Arguments :
  650. * hFile (IN) - Rasfile file handle for the INF file.
  651. *
  652. * Return Value :
  653. * FALSE if the current line is "NoEcho", else TRUE.
  654. */
  655. BOOL APIENTRY
  656. RasDevEchoExpected( HRASFILE hFile )
  657. {
  658. TCHAR szLine[RAS_MAXLINEBUFLEN];
  659. szLine[0] = TEXT('\0');
  660. RasfileGetLineText( hFile, szLine );
  661. return( ! (_strnicmp(szLine, MXS_NOECHO, strlen(MXS_NOECHO)) == 0) );
  662. }
  663. /*
  664. * RasDevIdFistCommand :
  665. * Determines the type of the first command in the section.
  666. *
  667. * Arguments :
  668. * hFile (IN) - Rasfile file handle for the INF file.
  669. *
  670. * Assumptions :
  671. * RasDevGetParams has been called previously, that is, the current
  672. * line is the first command.
  673. *
  674. * Return Value :
  675. * FALSE if current line is not a command, otherwise TRUE.
  676. */
  677. CMDTYPE APIENTRY
  678. RasDevIdFirstCommand( HRASFILE hFile )
  679. {
  680. //TCHAR szKey[MAX_PARAM_KEY_SIZE + 1];
  681. TCHAR *pszKey = NULL;
  682. CMDTYPE Type = CT_UNKNOWN;
  683. pszKey = malloc(RAS_MAXLINEBUFLEN);
  684. if(NULL == pszKey)
  685. {
  686. return CT_UNKNOWN;
  687. }
  688. ZeroMemory(pszKey, RAS_MAXLINEBUFLEN);
  689. // Find the first command
  690. do
  691. {
  692. if ( ! RasfileFindFirstLine(hFile,RFL_GROUP,RFS_SECTION))
  693. {
  694. break;
  695. }
  696. if ( ! RasfileGetKeyValueFields(hFile, pszKey, NULL))
  697. {
  698. break;
  699. }
  700. if (_stricmp(MXS_GENERIC_COMMAND, pszKey) == 0)
  701. {
  702. Type = CT_GENERIC;
  703. break;
  704. }
  705. else if (_stricmp(MXS_DIAL_COMMAND, pszKey) == 0)
  706. {
  707. Type = CT_DIAL;
  708. break;
  709. }
  710. else if (_stricmp(MXS_INIT_COMMAND, pszKey) == 0)
  711. {
  712. Type = CT_INIT;
  713. break;
  714. }
  715. else if (_stricmp(MXS_LISTEN_COMMAND, pszKey) == 0)
  716. {
  717. Type = CT_LISTEN;
  718. break;
  719. }
  720. }
  721. while(FALSE);
  722. free(pszKey);
  723. return Type;
  724. }
  725. /*
  726. * RasDevSubStr :
  727. * Finds a substring and returns a pointer to it. This function works like
  728. * the C runtime function strstr, but works in strings that contain zeros.
  729. *
  730. * Arguments :
  731. * psStr (IN) - the string to be searched for a substring
  732. * dwStrLen (IN) - length of the string to be searched
  733. * psSubStr (IN) - the substring to search for
  734. * dwSubStrLen (IN) - length of the substring
  735. *
  736. * Return Value :
  737. * A pointer to the beginning of the substring, or NULL if the substring
  738. * was not found.
  739. */
  740. LPTSTR APIENTRY
  741. RasDevSubStr( LPTSTR psStr,
  742. DWORD dwStrLen,
  743. LPTSTR psSubStr,
  744. DWORD dwSubStrLen )
  745. {
  746. LPTSTR ps;
  747. if (dwSubStrLen > dwStrLen)
  748. return NULL;
  749. for (ps = psStr; ps <= psStr + dwStrLen - dwSubStrLen; ps++)
  750. if (memcmp(ps, psSubStr, dwSubStrLen) == 0)
  751. return ps;
  752. return NULL;
  753. }
  754. /*****************************************************************************
  755. ** Rasfile Wrapper internal routines **
  756. ****************************************************************************/
  757. /*
  758. * rasDevGroupFunc :
  759. * The PFBISGROUP function passed to RasfileLoad().
  760. *
  761. * Arguments :
  762. * lpszLine (IN) - a Rasfile line
  763. *
  764. * Return Value :
  765. * TRUE if the line is a command line, FALSE otherwise.
  766. */
  767. BOOL rasDevGroupFunc( LPTSTR lpszLine )
  768. {
  769. TCHAR szKey[MAX_PARAM_KEY_SIZE], *lpszKey;
  770. if ( strcspn(lpszLine,"=") == strlen(lpszLine) )
  771. return FALSE;
  772. while ( *lpszLine == ' ' || *lpszLine == '\t' )
  773. lpszLine++;
  774. lpszKey = szKey;
  775. while ( *lpszLine != ' ' && *lpszLine != '\t' && *lpszLine != '=' )
  776. *lpszKey++ = *lpszLine++;
  777. *lpszKey = '\0';
  778. if ( ! _stricmp(szKey,"COMMAND") || ! _stricmp(szKey,"COMMAND_INIT") ||
  779. ! _stricmp(szKey,"COMMAND_DIAL") || ! _stricmp(szKey,"COMMAND_LISTEN") )
  780. return TRUE;
  781. else
  782. return FALSE;
  783. }
  784. /*
  785. * rasDevIsDecimalMacro :
  786. * Indicates whether or not a given macro must have only ascii
  787. * decimal digits for its value.
  788. *
  789. * Arguments:
  790. * lpszMacroName (IN) - macro name
  791. *
  792. * Return Value:
  793. * TRUE if only digits are legal in the macro value; otherwise FALSE.
  794. *
  795. * Remarks:
  796. * Called by API RasDevCheckResponse().
  797. */
  798. BOOL rasDevIsDecimalMacro ( LPTSTR lpszMacroName )
  799. {
  800. if (_stricmp(lpszMacroName, MXS_CONNECTBPS_KEY) == 0 ||
  801. _stricmp(lpszMacroName, MXS_CARRIERBPS_KEY) == 0)
  802. return(TRUE);
  803. else
  804. return(FALSE);
  805. }
  806. /*
  807. * rasDevGetMacroValue :
  808. * Extracts a macro value from string *lppszReceived and copies it
  809. * to string lpszMacro. Also updates the string pointer of
  810. * lppszValue and lppszReceived, and updates dRecLength.
  811. *
  812. * Arguments :
  813. * lppszReceived (INOUT) - received string (from a modem)
  814. * dRecLength (INOUT) - remaining length of the received string
  815. * lpszMacro (OUT) - buffer to receive the macro value
  816. *
  817. * Return Value :
  818. * None.
  819. *
  820. * Remarks :
  821. * Called by API RasDevCheckResponse().
  822. */
  823. void rasDevGetMacroValue ( LPTSTR *lppszReceived, DWORD *dRecLength,
  824. LPTSTR lpszMacroValue )
  825. {
  826. while ( **lppszReceived != CR && **lppszReceived != '\0' ) {
  827. *lpszMacroValue++ = *(*lppszReceived)++;
  828. (*dRecLength)--;
  829. }
  830. *lpszMacroValue = '\0'; // Null terminate the Macro value string
  831. }
  832. /*
  833. * rasDevGetDecimalMacroValue :
  834. * Extracts a macro value from string *lppszReceived and copies it
  835. * to string lpszMacro. Also updates the string pointer of
  836. * lppszReceived, and updates dRecLength.
  837. * This functions only extracts characters which are ascii decimal
  838. * digits.
  839. *
  840. * Arguments :
  841. * lppszReceived (INOUT) - received string (from a modem)
  842. * dRecLength (INOUT) - remaining length of the received string
  843. * lpszMacro (OUT) - buffer to receive the macro value
  844. *
  845. * Return Value :
  846. * None.
  847. *
  848. * Remarks :
  849. * Called by API RasDevCheckResponse().
  850. */
  851. void rasDevGetDecimalMacroValue ( LPTSTR *lppszReceived,
  852. DWORD *dRecLength,
  853. LPTSTR lpszMacroValue )
  854. {
  855. TCHAR szBuffer[16], *pBuf = szBuffer;
  856. WORD wcRightHandDigits = 0;
  857. BOOL bDpFound = FALSE;
  858. ULONG lBps;
  859. while ( isdigit(**lppszReceived) || **lppszReceived == '.' ) {
  860. if (isdigit(**lppszReceived)) {
  861. *pBuf++ = *(*lppszReceived)++;
  862. (*dRecLength)--;
  863. if (bDpFound)
  864. wcRightHandDigits++;
  865. }
  866. else if (!bDpFound && **lppszReceived == '.') {
  867. (*lppszReceived)++;
  868. (*dRecLength)--;
  869. bDpFound = TRUE;
  870. }
  871. else
  872. break;
  873. }
  874. *pBuf = '\0'; // Null terminate the Macro value string
  875. lBps = atol(szBuffer);
  876. switch(wcRightHandDigits)
  877. {
  878. case 0: case 3:
  879. break;
  880. case 1:
  881. lBps *= 100;
  882. break;
  883. case 2:
  884. lBps *= 10;
  885. break;
  886. }
  887. _ltoa(lBps, lpszMacroValue, 10);
  888. }
  889. /*
  890. * rasDevExpandMacros :
  891. * Takes the string lpszLine, and copies it to lpszVal, using
  892. * Macro Translation table pMacroXlations to expand macros.
  893. * <cr>, <lf>, and <hxx> macros are always expanded directly.
  894. * If bFlag == EXPAND_ALL << and >> are converted to < and >.
  895. * (A single > which is not at the end of a macro is simply copied.
  896. * An error could be raised here for such a >, but it is left to
  897. * be caught later when the device chokes on the unexpected >.
  898. * This has the advantage that a > where a >> should be will work.)
  899. *
  900. * Assumptions:
  901. * Expanded macros may contain zeros, therefore output command string
  902. * may contain zeros.
  903. *
  904. * Arguments :
  905. * lpszLine (IN) - a value string from a Rasfile keyword=value line
  906. * lpsVal (OUT) - buffer to copied to with expanded macros
  907. * pdwValLen (OUT) - length of output string with expanded macros
  908. * bFlag (IN) - EXPAND_FIXED_ONLY if only the fixed macros <cr>
  909. * and <lf> macros are to be expanded, and
  910. * EXPAND_ALL if all macros should be expanded
  911. * pMacroXlations (IN) - the Macro Translation table
  912. *
  913. * Return Value :
  914. * FALSE if a needed macro translation could not be found in the
  915. * pMacroXlations table, TRUE otherwise.
  916. *
  917. * Remarks :
  918. * Called by APIs RasDevGetCommand() and RasDevCheckResponse().
  919. */
  920. BOOL rasDevExpandMacros( LPTSTR lpszLine,
  921. LPTSTR lpsVal,
  922. DWORD *pdwValLen,
  923. BYTE bFlag,
  924. MACROXLATIONTABLE *pMacroXlations )
  925. {
  926. TCHAR szMacro[RAS_MAXLINEBUFLEN];
  927. LPTSTR lpsValue;
  928. lpsValue = lpsVal;
  929. for ( ; *lpszLine != '\0'; ) {
  930. // check for RMSCH
  931. // if EXPAND_ALL convert double RMSCH to single RMSCH, and
  932. // simply copy single RMSCH.
  933. if ((bFlag & EXPAND_ALL) && *lpszLine == RMSCH) {
  934. *lpsValue++ = *lpszLine++;
  935. if (*lpszLine == RMSCH)
  936. lpszLine++;
  937. }
  938. // check for a macro or double LMSCH
  939. else if ( *lpszLine == LMSCH ) {
  940. if ((bFlag & EXPAND_ALL) && *(lpszLine + 1) == LMSCH) {
  941. *lpsValue++ = *lpszLine;
  942. lpszLine += 2;
  943. }
  944. else if ( ! _strnicmp(lpszLine,CR_MACRO,4) ) {
  945. *lpsValue++ = CR;
  946. lpszLine += 4;
  947. }
  948. else if ( ! _strnicmp(lpszLine,LF_MACRO,4) ) {
  949. *lpsValue++ = LF;
  950. lpszLine += 4;
  951. }
  952. else if ( ! _strnicmp(lpszLine,APPEND_MACRO,8) &&
  953. (bFlag & EXPAND_ALL) )
  954. lpszLine += 8;
  955. // Hex macro stuff
  956. //
  957. else if ((lpszLine[1] == 'h' || lpszLine[1] == 'H') &&
  958. isxdigit(lpszLine[2]) && isxdigit(lpszLine[3]) &&
  959. (lpszLine[4] == RMSCH) &&
  960. ( bFlag & EXPAND_ALL )) {
  961. char c;
  962. c = (char) (ctox(lpszLine[2]) * 0x10 + ctox(lpszLine[3]));
  963. lpszLine += 5; // '<', 'h', two hex digits, and '>'
  964. *lpsValue++ = c;
  965. }
  966. else if ( bFlag & EXPAND_ALL ) {
  967. LPTSTR lpszStr;
  968. char buf[256];
  969. for ( lpszLine++, lpszStr = szMacro; *lpszLine != RMSCH; )
  970. *lpszStr++ = *lpszLine++;
  971. lpszLine++; // advance past RMSCH
  972. *lpszStr = '\0'; // Null terminate szMacro string
  973. if ( ! rasDevLookupMacro(szMacro,&lpsValue,pMacroXlations) )
  974. return FALSE;
  975. }
  976. else {
  977. // just copy the macro if EXPAND_ALL is not set
  978. while ( *lpszLine != RMSCH )
  979. *lpsValue++ = *lpszLine++;
  980. *lpsValue++ = *lpszLine++;
  981. }
  982. }
  983. else
  984. *lpsValue++ = *lpszLine++;
  985. } // for
  986. *lpsValue = '\0';
  987. *pdwValLen = (DWORD) (lpsValue - lpsVal);
  988. return TRUE;
  989. }
  990. /*
  991. * rasDevLookupMacro :
  992. * Lookup macro lpszMacro in the given Macro Translation table, and
  993. * return it's value in *lppszExpanded if found.
  994. *
  995. * Arguments :
  996. * lpszMacro (IN) - the macro whose value is sought
  997. * lppszExpanded (OUT) - double pointer to increment and copy the
  998. * macro's value to
  999. * pMacroXlations (IN) - the Macro Translation table
  1000. *
  1001. * Return Value :
  1002. * FALSE if the macro could not be found in the given Macro Translation
  1003. * table, TRUE otherwise.
  1004. *
  1005. * Remarks :
  1006. * Called by internal function rasDevExpandMacros().
  1007. */
  1008. BOOL rasDevLookupMacro( LPTSTR lpszMacro, LPTSTR *lppszExpanded,
  1009. MACROXLATIONTABLE *pMacroXlations )
  1010. {
  1011. WORD i;
  1012. LPTSTR lpszMacroValue;
  1013. for ( i = 0; i < pMacroXlations->MXT_NumOfEntries; i++ ) {
  1014. if ( ! _stricmp(pMacroXlations->MXT_Entry[i].E_MacroName, lpszMacro) ) {
  1015. lpszMacroValue =
  1016. pMacroXlations->MXT_Entry[i].E_Param->P_Value.String.Data;
  1017. while (*lpszMacroValue != 0) {
  1018. **lppszExpanded = *lpszMacroValue; // copy macro char by char
  1019. if ((*lpszMacroValue == LMSCH && *(lpszMacroValue+1) == LMSCH)
  1020. || (*lpszMacroValue == RMSCH && *(lpszMacroValue+1) == RMSCH))
  1021. lpszMacroValue++; // skip one of double angle brackets
  1022. lpszMacroValue++;
  1023. (*lppszExpanded)++;
  1024. }
  1025. return TRUE;
  1026. }
  1027. }
  1028. return FALSE;
  1029. }
  1030. /*
  1031. * rasDevMacroInsert :
  1032. * Updates the value of macro lpszMacro with new value lpszNewValue
  1033. * in the given Macro Translation table.
  1034. *
  1035. * Arguments :
  1036. * aszMacros (IN) - array of macro name and value pairs
  1037. * wMacros (IN) - number of elements of aszMacros array
  1038. * pMacroXlations (INOUT) - the Macro Translation table
  1039. *
  1040. * Return Value : SUCCESS
  1041. * ERROR_MACRO_NOT_DEFINED
  1042. *
  1043. * Remarks :
  1044. * Called by API RasDevCheckResponse().
  1045. */
  1046. DWORD rasDevMacroInsert( MACRO *aszMacros, WORD wMacros,
  1047. MACROXLATIONTABLE *pMacroXlations )
  1048. {
  1049. int iMacros;
  1050. WORD iXlations;
  1051. DWORD dwRC;
  1052. for ( iMacros = (int)(wMacros - 1); iMacros >= 0; iMacros-- ) {
  1053. for ( iXlations = 0; iXlations < pMacroXlations->MXT_NumOfEntries;
  1054. iXlations++ ) {
  1055. if ( ! _stricmp(pMacroXlations->MXT_Entry[iXlations].E_MacroName,
  1056. aszMacros[iMacros].MacroName) ) {
  1057. dwRC = UpdateParamString(pMacroXlations->MXT_Entry[iXlations].E_Param,
  1058. aszMacros[iMacros].MacroValue,
  1059. strlen(aszMacros[iMacros].MacroValue));
  1060. if (dwRC != SUCCESS)
  1061. return dwRC;
  1062. break;
  1063. }
  1064. }
  1065. if ( iXlations == pMacroXlations->MXT_NumOfEntries )
  1066. return ERROR_MACRO_NOT_DEFINED;
  1067. }
  1068. return SUCCESS;
  1069. }
  1070. /*
  1071. * rasDevExtractKey :
  1072. * Extracts the keyvalue from a Rasfile line.
  1073. *
  1074. * Arguments :
  1075. * lpszString (IN) - Rasfile line pointer.
  1076. * lpszKey (OUT) - buffer to hold the keyvalue
  1077. *
  1078. * Return Value :
  1079. * None.
  1080. *
  1081. * Remarks :
  1082. * Called by APIs RasDevGetParams(), RasDevGetCommand(), and
  1083. * RasDevCheckResponse(), and internal functions rasDevCheckParams()
  1084. * and rasDevCheckMacros().
  1085. */
  1086. void rasDevExtractKey ( LPTSTR lpszString, LPTSTR lpszKey )
  1087. {
  1088. // skip to beginning of keyword (skip '<' if present)
  1089. while ( *lpszString == ' ' || *lpszString == '\t' ||
  1090. *lpszString == LMSCH )
  1091. lpszString++;
  1092. while ( *lpszString != RMSCH && *lpszString != '=' &&
  1093. *lpszString != ' ' && *lpszString != '\t' )
  1094. *lpszKey++ = *lpszString++;
  1095. *lpszKey = '\0'; // Null terminate keyword string
  1096. }
  1097. /*
  1098. * rasDevExtractValue :
  1099. * Extracts the value string for a keyword=value string which
  1100. * begins on Rasfile line lpszString. This function recongizes a
  1101. * backslash \ as a line continuation character and a double
  1102. * backslash \\ as a backslash character.
  1103. *
  1104. * Assumptions: lpszValue output buffer is ALWAYS large enough.
  1105. *
  1106. * Arguments :
  1107. * lpszString (IN) - Rasfile line where the keyword=value string begins
  1108. * lpszValue (OUT) - buffer to hold the value string
  1109. * dSize (IN) - size of the lpszValue buffer
  1110. * hFile (IN) - Rasfile handle, the current line must be the line
  1111. * which lpszString points to
  1112. *
  1113. * Return Value :
  1114. * None.
  1115. *
  1116. * Remarks :
  1117. * Called by APIs RasDevGetParams(), RasDevGetCommand(), and
  1118. * RasDevCheckResponse().
  1119. */
  1120. void rasDevExtractValue ( LPTSTR lpszString, LPTSTR lpszValue,
  1121. DWORD dSize, HRASFILE hFile )
  1122. {
  1123. LPTSTR lpszInputStr;
  1124. BOOL bLineContinues;
  1125. // skip to beginning of value string
  1126. for ( lpszString += strcspn(lpszString,"=") + 1;
  1127. *lpszString == ' ' || *lpszString == '\t'; lpszString++ )
  1128. ;
  1129. // check for continuation lines
  1130. if ( strcspn(lpszString,"\\") == strlen(lpszString) )
  1131. strcpy(lpszValue,lpszString); // copy value string
  1132. else {
  1133. memset(lpszValue,0,dSize);
  1134. lpszInputStr = lpszString;
  1135. for (;;) {
  1136. // copy the current line
  1137. bLineContinues = FALSE;
  1138. while (*lpszInputStr != '\0') {
  1139. if (*lpszInputStr == '\\')
  1140. if (*(lpszInputStr + 1) == '\\') {
  1141. *lpszValue++ = *lpszInputStr; // copy one backslash
  1142. lpszInputStr += 2;
  1143. }
  1144. else {
  1145. bLineContinues = TRUE;
  1146. break;
  1147. }
  1148. else
  1149. *lpszValue++ = *lpszInputStr++;
  1150. }
  1151. if ( ! bLineContinues)
  1152. break;
  1153. // get the next line
  1154. if ( ! RasfileFindNextLine(hFile,RFL_ANYACTIVE,RFS_SECTION) )
  1155. break;
  1156. lpszInputStr = (LPTSTR)RasfileGetLine(hFile);
  1157. }
  1158. }
  1159. }
  1160. /*
  1161. * rasDevSortParams :
  1162. * Sorts an array of Rasfile lines by keyvalue.
  1163. *
  1164. * Arguments :
  1165. * alpszLines (INOUT) - the array of line pointers
  1166. * dParams (IN) - number of elements in the array
  1167. *
  1168. * Return Value :
  1169. * None.
  1170. *
  1171. * Remarks :
  1172. * Called by API RasDevGetParams().
  1173. */
  1174. void rasDevSortParams( LPTSTR *alpszLines, DWORD dParams )
  1175. {
  1176. TCHAR szKey1[MAX_PARAM_KEY_SIZE], szKey2[MAX_PARAM_KEY_SIZE];
  1177. LPTSTR lpszTemp;
  1178. DWORD i,j;
  1179. BOOL changed;
  1180. // If there is nothing to sort, don't try
  1181. if (dParams < 2)
  1182. return;
  1183. /* Bubble sort - it's stable */
  1184. for ( i = dParams - 1; i > 0; i-- ) {
  1185. changed = FALSE;
  1186. for ( j = 0; j < i; j++ ) {
  1187. rasDevExtractKey(alpszLines[j],szKey1);
  1188. rasDevExtractKey(alpszLines[j+1],szKey2);
  1189. // sort by keyvalue
  1190. if ( _stricmp(szKey1,szKey2) > 0 ) {
  1191. lpszTemp = alpszLines[j];
  1192. alpszLines[j] = alpszLines[j+1];
  1193. alpszLines[j+1] = lpszTemp;
  1194. changed = TRUE;
  1195. }
  1196. }
  1197. if ( ! changed )
  1198. return;
  1199. }
  1200. }
  1201. /*
  1202. * rasDevCheckParams :
  1203. * Removes duplicate lines from the alpszLines array of lines.
  1204. * Duplicates lines are those whose keyvalue is identical. The
  1205. * line with the lesser index is removed.
  1206. *
  1207. * Arguments :
  1208. * alpszLines (INOUT) - the array of line pointers
  1209. * pdTotalParams (INOUT) - number of array entries, this is updated
  1210. * if duplicates are removed
  1211. *
  1212. * Return Value :
  1213. * None.
  1214. *
  1215. * Remarks :
  1216. * Called by API RasDevGetParams().
  1217. */
  1218. void rasDevCheckParams( LPTSTR *alpszLines, DWORD *pdTotalParams )
  1219. {
  1220. TCHAR szKey1[MAX_PARAM_KEY_SIZE], szKey2[MAX_PARAM_KEY_SIZE];
  1221. DWORD dParams, i;
  1222. dParams = *pdTotalParams;
  1223. for ( i = 1; i < *pdTotalParams ; i++ ) {
  1224. rasDevExtractKey(alpszLines[i-1],szKey1);
  1225. rasDevExtractKey(alpszLines[i],szKey2);
  1226. if ( _stricmp(szKey1,szKey2) == 0 ) {
  1227. memcpy(&(alpszLines[i-1]),&(alpszLines[i]),
  1228. (*pdTotalParams - i) * sizeof(LPTSTR *));
  1229. (*pdTotalParams)--;
  1230. }
  1231. }
  1232. }
  1233. /*
  1234. * rasDevCheckMacros :
  1235. * Checks the array of lines for missing _ON or _OFF macros
  1236. * in binary macro pairs and inserts any such missing macro
  1237. * into the array of lines.
  1238. *
  1239. * Arguments :
  1240. * alpszLines (INOUT) - array of lines
  1241. * alpszMallocedLines (OUT) - array of newly malloced lines for
  1242. * this routine
  1243. * pdTotalParams (INOUT) - total number of elements in alpszLines
  1244. * array, this is updated if new entries are
  1245. * added
  1246. *
  1247. * Return Value :
  1248. * None.
  1249. *
  1250. * Remarks :
  1251. * Called by API RasDevGetParams().
  1252. */
  1253. void rasDevCheckMacros( LPTSTR *alpszLines, LPTSTR *alpszMallocedLines,
  1254. DWORD *pdTotalParams )
  1255. {
  1256. TCHAR szKey1[MAX_PARAM_KEY_SIZE], szKey2[MAX_PARAM_KEY_SIZE];
  1257. DWORD i, j;
  1258. BYTE bMissing;
  1259. if(alpszLines == NULL)
  1260. {
  1261. return;
  1262. }
  1263. // insert missing _ON and _OFF macros
  1264. for ( i = 0; i < *pdTotalParams; i++ ) {
  1265. if ( strcspn(alpszLines[i],LMS) > strcspn(alpszLines[i],"=") )
  1266. continue; // not a macro
  1267. bMissing = NONE;
  1268. rasDevExtractKey(alpszLines[i],szKey1);
  1269. // if current key is an _OFF macro, check for a missing _ON
  1270. if ( strstr(szKey1,"_OFF") != NULL || strstr(szKey1,"_off") != NULL ) {
  1271. if ( i+1 == *pdTotalParams ) // looking at last parameter
  1272. bMissing = ON;
  1273. // get next key
  1274. else {
  1275. rasDevExtractKey(alpszLines[i+1],szKey2);
  1276. if (_strnicmp(szKey1,szKey2,strlen(szKey1) - strlen("OFF")) != 0)
  1277. bMissing = ON;
  1278. }
  1279. }
  1280. // if current key is an _ON macro, check for a missing _OFF
  1281. if ( strstr(szKey1,"_ON") != NULL || strstr(szKey1,"_on") != NULL ) {
  1282. if ( i == 0 ) // looking at first parameter
  1283. bMissing = OFF;
  1284. // get previous key
  1285. else {
  1286. rasDevExtractKey(alpszLines[i-1],szKey2);
  1287. if (_strnicmp(szKey1,szKey2,strlen(szKey1) - strlen("ON")) != 0)
  1288. bMissing = OFF;
  1289. }
  1290. }
  1291. if ( bMissing != NONE ) {
  1292. // shift everything over one position
  1293. for ( j = *pdTotalParams - 1;
  1294. j >= i + ((bMissing == ON) ? 1 : 0); j-- )
  1295. alpszLines[j+1] = alpszLines[j];
  1296. // point j to the new empty array entry
  1297. j = (bMissing == OFF) ? i : i + 1;
  1298. alpszLines[j] = malloc(sizeof(TCHAR) * RAS_MAXLINEBUFLEN);
  1299. if(NULL == alpszLines[j])
  1300. {
  1301. *alpszMallocedLines = NULL;
  1302. return;
  1303. }
  1304. *alpszMallocedLines++ = alpszLines[j];
  1305. memset(alpszLines[j],0,sizeof(TCHAR) * RAS_MAXLINEBUFLEN);
  1306. strcpy(alpszLines[j],LMS);
  1307. if ( bMissing == ON )
  1308. strncat(alpszLines[j],szKey1,
  1309. strlen(szKey1) - strlen(OFF_STR));
  1310. else // bMissing == OFF
  1311. strncat(alpszLines[j],szKey1,
  1312. strlen(szKey1) - strlen(ON_STR));
  1313. strcat(alpszLines[j], bMissing == ON ? ON_STR : OFF_STR );
  1314. strcat(alpszLines[j], RMS);
  1315. strcat(alpszLines[j], "=");
  1316. (*pdTotalParams)++;
  1317. i++; // increment i to compensate for the new entry
  1318. }
  1319. } // for
  1320. // Null terminate the Malloced Lines array
  1321. *alpszMallocedLines = NULL;
  1322. }
  1323. /*
  1324. * ctox :
  1325. * Convert char hex digit to decimal number.
  1326. */
  1327. BYTE ctox( char ch )
  1328. {
  1329. if ( isdigit(ch) )
  1330. return ch - '0';
  1331. else
  1332. return (tolower(ch) - 'a') + 10;
  1333. }
  1334. //* UpdateParamString ------------------------------------------------------
  1335. //
  1336. // Function: This function copys a new string into a PARAM.P_Value
  1337. // allocating new memory of the new string is longer than
  1338. // the old. The copied string is then zero terminated.
  1339. //
  1340. // NOTE: This function frees and allocates memory and is not
  1341. // suitable for copying into an existing buffer. Use with
  1342. // InfoTable and other RAS_PARAMS with 'unpacked' strings.
  1343. //
  1344. // Arguments:
  1345. // pParam OUT Pointer to Param to update
  1346. // psStr IN Input string
  1347. // dwStrLen IN Length of input string
  1348. //
  1349. // Returns: SUCCESS
  1350. // ERROR_ALLOCATING_MEMORY
  1351. //*
  1352. DWORD
  1353. UpdateParamString(RAS_PARAMS *pParam, TCHAR *psStr, DWORD dwStrLen)
  1354. {
  1355. if (dwStrLen > pParam->P_Value.String.Length)
  1356. {
  1357. free(pParam->P_Value.String.Data);
  1358. GetMem(dwStrLen + 1, &(pParam->P_Value.String.Data));
  1359. if (pParam->P_Value.String.Data == NULL)
  1360. return(ERROR_ALLOCATING_MEMORY);
  1361. }
  1362. pParam->P_Value.String.Length = dwStrLen;
  1363. memcpy(pParam->P_Value.String.Data, psStr, dwStrLen);
  1364. pParam->P_Value.String.Data[dwStrLen] = '\0'; //Zero Terminate
  1365. return(SUCCESS);
  1366. }
  1367. //* GetMem -----------------------------------------------------------------
  1368. //
  1369. // Function: Allocates memory. If the memory allocation fails the output
  1370. // parameter will be NULL.
  1371. //
  1372. // Returns: Nothing.
  1373. //
  1374. //*
  1375. void
  1376. GetMem(DWORD dSize, BYTE **ppMem)
  1377. {
  1378. *ppMem = (BYTE *) calloc(dSize, 1);
  1379. }