Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

641 lines
14 KiB

  1. /*
  2. * Infparse.c - Setup.inf parsing code.
  3. * Clark Cyr, Mike Colee, Todd Laney
  4. * Copyright (C) Microsoft, 1989
  5. * March 15, 1989
  6. *
  7. * Modification History:
  8. *
  9. * 3/15/89 CC Clark wrote this code for control Panel. This is windows
  10. * code.
  11. *
  12. * 3/20/89 MC Decided this code would work for Dos and windows portion
  13. * of setup. take out windows specifc stuff like local alloc's
  14. * and dialog stuff. Replace it with standard C run time calls.
  15. *
  16. * 3/24/89 Toddla TOTAL rewrite! nothing is the same any more.
  17. *
  18. * 6/29/89 MC fixed getprofilestring func to not strip quotes if more
  19. * than one field exists.
  20. */
  21. #include <windows.h>
  22. #include <mmsystem.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include "drivers.h"
  26. #include "sulib.h"
  27. /*** hack. to avoid realloc problems we make READ_BUFSIZE
  28. as big as the inf file, thus avoiding any reallocs */
  29. #define READ_BUFSIZE 27000 /* size of inf buffer */
  30. #define TMP_BUFSIZE 1024 /* size of temp reads */
  31. #define EOF 0x1A
  32. #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0' || (c) == EOF)
  33. #define ISSEP(c) ((c) == '=' || (c) == ',')
  34. #define ISWHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
  35. #define ISNOISE(c) ((c) == '"')
  36. #define QUOTE '"'
  37. #define EQUAL '='
  38. PINF pinfDefault = NULL;
  39. static PSTR pBuf;
  40. static PINF pInf;
  41. static UINT iBuf;
  42. static UINT iInf;
  43. /* Globaly used pointers to non-translatable text strings. */
  44. extern char *pszPATH;
  45. /* Local prototypes */
  46. BOOL multifields(PINF);
  47. static char GETC(int fh)
  48. {
  49. register UINT n;
  50. if (!pBuf)
  51. return EOF;
  52. n = iBuf % TMP_BUFSIZE;
  53. if (n == 0)
  54. {
  55. _lread(fh,pBuf,TMP_BUFSIZE);
  56. }
  57. iBuf++;
  58. return pBuf[n];
  59. }
  60. static void PUTC(char c)
  61. {
  62. if (!pInf)
  63. return;
  64. pInf[iInf++] = c;
  65. }
  66. static void MODIFYC(char c)
  67. {
  68. if (!pInf)
  69. return;
  70. pInf[iInf++ - 1] = c;
  71. }
  72. static char LASTC(void) {
  73. if (!pInf) return ' ';
  74. if (iInf == 0) {
  75. return ' ';
  76. }
  77. return pInf[iInf - 1];
  78. }
  79. /* int infLoadFile() Load a entire INF file into memory
  80. * comments are removed, each line is terminated
  81. * by a \0 each section is terminated by a \0\0
  82. * ONLY spaces inside of " " are preserved
  83. * the end of file is marked with a ^Z
  84. *
  85. * RETURNS: A pointer to a block of memory containg file, NULL if failure
  86. *
  87. */
  88. PINF infLoadFile(int fh)
  89. {
  90. UINT len;
  91. char c;
  92. BOOL fQuote = FALSE;
  93. BOOL inSectionName = FALSE;
  94. if (fh == -1)
  95. return NULL;
  96. len = (UINT)_llseek(fh,0L,SEEK_END);
  97. _llseek(fh,0L,SEEK_SET);
  98. iBuf = 0;
  99. iInf = 0;
  100. pBuf = ALLOC(TMP_BUFSIZE); // temp buffer
  101. if (!pBuf)
  102. return NULL;
  103. pInf = FALLOC(len); // destination, at least as big as file
  104. if (!pInf) {
  105. FREE((HANDLE)pBuf);
  106. return NULL;
  107. }
  108. while (iBuf < len)
  109. {
  110. c = GETC(fh);
  111. loop:
  112. if (iBuf >= len)
  113. break;
  114. switch (c)
  115. {
  116. case '[':
  117. inSectionName = TRUE;
  118. PUTC(c);
  119. break;
  120. case ']':
  121. if (inSectionName) {
  122. if (LASTC() == ' ') {
  123. MODIFYC(c);
  124. } else {
  125. PUTC(c);
  126. }
  127. inSectionName = FALSE;
  128. } else {
  129. PUTC(c);
  130. }
  131. break;
  132. case '\r': /* ignore '\r' */
  133. break;
  134. case '\n':
  135. for (; ISWHITE(c); c = GETC(fh))
  136. ;
  137. if (c != ';')
  138. PUTC(0); /* all lines end in a \0 */
  139. if (c == '[') {
  140. PUTC(0); /* all sections end with \0\0 */
  141. }
  142. fQuote = FALSE;
  143. goto loop;
  144. break;
  145. case '\t':
  146. case ' ':
  147. if (inSectionName) {
  148. if (LASTC() != ' ' && LASTC() != ']')
  149. PUTC(' ');
  150. } else {
  151. if (fQuote)
  152. PUTC(c);
  153. }
  154. break;
  155. case '"':
  156. fQuote = !fQuote;
  157. PUTC(c);
  158. break;
  159. case ';':
  160. for (; !ISEOL(c); c = GETC(fh))
  161. ;
  162. goto loop;
  163. break;
  164. default:
  165. PUTC(c);
  166. break;
  167. }
  168. }
  169. PUTC(0);
  170. PUTC(0);
  171. PUTC(EOF);
  172. FREE((HANDLE)pBuf);
  173. // try to shrink this block
  174. // just leave pInf it's original size. don't bother shrinking it
  175. return pInf;
  176. }
  177. /* PINF FAR PASCAL infOpen()
  178. * PARAMETERS
  179. * szInf - path to inf file to open and load
  180. *
  181. * RETURNS: A pointer to the parsed inf file if successful,
  182. * Null pointer in the case of failure.
  183. *
  184. * ENTER:
  185. * EXIT: To caller
  186. */
  187. PINF infOpen(LPSTR szInf)
  188. {
  189. char szBuf[MAX_PATH];
  190. int fh;
  191. PINF pinf;
  192. fh = -1;
  193. if (szInf == NULL)
  194. szInf = szSetupInf;
  195. /*
  196. * Next try to open passed parameter as is. For Dos half.
  197. */
  198. if (fh == -1)
  199. {
  200. fh = _lopen(szInf, OF_READ);
  201. }
  202. /*
  203. * Next try destination path\system32. for win half.
  204. */
  205. if (fh == -1) {
  206. lstrcpy(szBuf, szSetupPath);
  207. catpath(szBuf, "system32");
  208. catpath(szBuf, szInf);
  209. fh = _lopen(szBuf, OF_READ);
  210. }
  211. /*
  212. * Next try destination path. for initial setup.
  213. */
  214. if (fh == -1) {
  215. lstrcpy(szBuf, szSetupPath);
  216. catpath(szBuf, szInf);
  217. fh = _lopen(szBuf, OF_READ);
  218. }
  219. if (fh != -1)
  220. {
  221. pinf = infLoadFile(fh);
  222. _lclose(fh);
  223. if (pinf && !pinfDefault)
  224. pinfDefault = pinf;
  225. return pinf;
  226. }
  227. return NULL;
  228. }
  229. /* void FAR PASCAL infClose(PINF pinf)
  230. *
  231. * ENTER:
  232. * EXIT: To caller
  233. */
  234. void infClose(PINF pinf)
  235. {
  236. if (pinf == NULL)
  237. pinf = pinfDefault;
  238. if (pinf != NULL)
  239. {
  240. FFREE(pinf);
  241. if (pinf == pinfDefault)
  242. pinfDefault = NULL;
  243. }
  244. }
  245. /* FindSection locates a section in Setup.Inf. Sections are
  246. * assumed to be delimited by a '[' as the first
  247. * character on a line.
  248. *
  249. * Arguments: pInf Pointer to SETUP.INF buffer
  250. * pszSect LPSTR to section name
  251. *
  252. * Return: UINT file position of the first line in the section
  253. * 0 if section not found
  254. */
  255. UINT FindSection(PINF pInf, LPSTR pszSect)
  256. {
  257. BOOL fFound = FALSE;
  258. int nLen = lstrlen(pszSect);
  259. PINF pch;
  260. if (!pInf)
  261. return 0;
  262. pch = pInf;
  263. while (!fFound && *pch != EOF)
  264. {
  265. if (*pch++ == '[')
  266. {
  267. fFound = !strnicmp(pszSect, pch, nLen) && pch[nLen] == ']';
  268. }
  269. /*
  270. * go to the next line, dont forget to skip over \0 and \0\0
  271. */
  272. while (*pch != EOF && *pch != '\0')
  273. pch++;
  274. while (*pch == 0)
  275. pch++;
  276. }
  277. return((fFound && *pch != '[' && *pch != EOF) ? pch - pInf : 0);
  278. }
  279. /* char* fnGetDataString(npszData,szDataStr)
  280. *
  281. * Called by functions that read sections of information from setup.inf
  282. * to obtain strings that are set equal to keywords. Example:
  283. *
  284. * welcome=("Hello There")
  285. *
  286. * This function will return a pointer to the null terminated string
  287. * "Hello There".
  288. *
  289. * ENTRY:
  290. *
  291. * npszData : pointer to entire section taken from setup.inf
  292. * npszDataStr : pointer to key word to look for (welcome in example above.)
  293. *
  294. * EXIT: returns pointer to string if successful, NULL if failure.
  295. *
  296. */
  297. BOOL fnGetDataString(PINF npszData, LPSTR szDataStr, LPSTR szBuf)
  298. {
  299. int len = lstrlen(szDataStr);
  300. while (npszData)
  301. {
  302. if (!strnicmp(npszData,szDataStr,len)) // looking for correct prof.
  303. {
  304. npszData += len; // found !, look past prof str.
  305. while (ISWHITE(*npszData)) // pull out the stuff.
  306. npszData++;
  307. if (*npszData == EQUAL) // Now we have what were looking for !
  308. {
  309. npszData++;
  310. if (!multifields(npszData) )
  311. {
  312. while (ISWHITE(*npszData) || ISNOISE(*npszData))
  313. npszData++;
  314. while (*npszData)
  315. *szBuf++ = *npszData++;
  316. /*
  317. * remove trailing spaces, and those pesky ()'s
  318. */
  319. while (ISWHITE(szBuf[-1]) || ISNOISE(szBuf[-1]))
  320. szBuf--;
  321. *szBuf = 0;
  322. return TRUE;
  323. }
  324. else
  325. {
  326. while (*npszData)
  327. *szBuf++ = *npszData++;
  328. *szBuf = '\0';
  329. return TRUE;
  330. }
  331. }
  332. }
  333. npszData = infNextLine(npszData);
  334. }
  335. *szBuf = 0;
  336. return FALSE;
  337. }
  338. /* PINF FAR PASCAL infSetDefault(pinf)
  339. *
  340. * Sets the default INF file
  341. *
  342. * ENTRY:
  343. * pinf : inf file to be new default
  344. *
  345. * EXIT: returns old default
  346. *
  347. */
  348. PINF infSetDefault(PINF pinf)
  349. {
  350. PINF pinfT;
  351. pinfT = pinfDefault;
  352. pinfDefault = pinf;
  353. return pinfT;
  354. }
  355. /* PINF FAR PASCAL infFindSection(pinf,szSection)
  356. *
  357. * Reads a entire section into memory and returns a pointer to it
  358. *
  359. * ENTRY:
  360. * pinf : inf file to search for section
  361. * szSection : section name to read
  362. *
  363. * EXIT: returns pointer to section, NULL if error
  364. *
  365. */
  366. PINF infFindSection(PINF pinf, LPSTR szSection)
  367. {
  368. UINT pos;
  369. if (pinf == NULL)
  370. pinf = pinfDefault;
  371. pos = FindSection(pinf, szSection);
  372. return pos ? pinf + pos : NULL;
  373. }
  374. /* BOOL FAR PASCAL infGetProfileString(szSection,szItem,szBuf)
  375. *
  376. * Reads a single string from a section in SETUP.INF
  377. *
  378. * [section]
  379. * item = string
  380. *
  381. * ENTRY:
  382. * szSection : pointer to section name to read.
  383. * szItem : pointer to item name to read
  384. * szBuf : pointer to a buffer to hold result
  385. *
  386. * EXIT: returns TRUE if successful, FALSE if failure.
  387. *
  388. */
  389. BOOL infGetProfileString(PINF pinf, LPSTR szSection,LPSTR szItem,LPSTR szBuf)
  390. {
  391. PINF pSection;
  392. pSection = infFindSection(pinf,szSection);
  393. if (pSection )
  394. return fnGetDataString(pSection,szItem,szBuf);
  395. else
  396. *szBuf = 0;
  397. return FALSE;
  398. }
  399. /* BOOL FAR PASCAL infParseField(szData,n,szBuf)
  400. *
  401. * Given a line from SETUP.INF, will extract the nth field from the string
  402. * fields are assumed separated by comma's. Leading and trailing spaces
  403. * are removed.
  404. *
  405. * ENTRY:
  406. *
  407. * szData : pointer to line from SETUP.INF
  408. * n : field to extract. ( 1 based )
  409. * 0 is field before a '=' sign
  410. * szBuf : pointer to buffer to hold extracted field
  411. *
  412. * EXIT: returns TRUE if successful, FALSE if failure.
  413. *
  414. */
  415. BOOL infParseField(PINF szData, int n, LPSTR szBuf)
  416. {
  417. BOOL fQuote = FALSE;
  418. PINF pch;
  419. LPSTR ptr;
  420. if (!szData || !szBuf)
  421. return FALSE;
  422. /*
  423. * find the first separator
  424. */
  425. for (pch=szData; *pch && !ISSEP(*pch); pch++) {
  426. if ( *pch == QUOTE )
  427. fQuote = !fQuote;
  428. }
  429. if (n == 0 && *pch != '=')
  430. return FALSE;
  431. if (n > 0 && *pch == '=' && !fQuote)
  432. szData = ++pch;
  433. /*
  434. * locate the nth comma, that is not inside of quotes
  435. */
  436. fQuote = FALSE;
  437. while (n > 1)
  438. {
  439. while (*szData)
  440. {
  441. if (!fQuote && ISSEP(*szData))
  442. break;
  443. if (*szData == QUOTE)
  444. fQuote = !fQuote;
  445. szData++;
  446. }
  447. if (!*szData) {
  448. szBuf[0] = 0; // make szBuf empty
  449. return FALSE;
  450. }
  451. szData++;
  452. n--;
  453. }
  454. /*
  455. * now copy the field to szBuf
  456. */
  457. while (ISWHITE(*szData))
  458. szData++;
  459. fQuote = FALSE;
  460. ptr = szBuf; // fill output buffer with this
  461. while (*szData)
  462. {
  463. if (*szData == QUOTE)
  464. fQuote = !fQuote;
  465. else if (!fQuote && ISSEP(*szData))
  466. break;
  467. else
  468. *ptr++ = *szData;
  469. szData++;
  470. }
  471. /*
  472. * remove trailing spaces, and those pesky ()'s
  473. */
  474. while ((ptr > szBuf) && (ISWHITE(ptr[-1]) || ISNOISE(ptr[-1])))
  475. ptr--;
  476. *ptr = 0;
  477. return TRUE;
  478. }
  479. /* BOOL multifields(LPSTR npszData);
  480. *
  481. * Given a line line from mmdriver.inf that was after a profile
  482. * string this function will determine if that line has more than one
  483. * field. ie. Fields are seperated by commas that are NOT contained between
  484. * quotes.
  485. *
  486. * ENYRY:
  487. *
  488. * npszData : a line from setup.inf Example "xyz adapter",1:foobar.drv
  489. *
  490. * EXIT: This function will return TRUE if the line containes more than
  491. * one field, ie the function would return TRUE for the example line
  492. * shown above.
  493. *
  494. */
  495. BOOL multifields(PINF npszData)
  496. {
  497. BOOL fQuote = FALSE;
  498. while (*npszData)
  499. {
  500. if (!fQuote && ISSEP(*npszData))
  501. return TRUE;
  502. if (*npszData == QUOTE)
  503. fQuote = !fQuote;
  504. npszData++;
  505. }
  506. return FALSE;
  507. }
  508. /* LPSTR FAR PASCAL infNextLine(sz)
  509. *
  510. * Given a line from SETUP.INF, advance to the next line. will skip past the
  511. * ending NULL character checking for end of buffer \0\0
  512. *
  513. * ENTRY:
  514. *
  515. * sz : pointer to line from a SETUP.INF section
  516. *
  517. * EXIT: returns pointer to next line if successful, NULL if failure.
  518. *
  519. */
  520. PINF infNextLine(PINF pinf)
  521. {
  522. if (!pinf)
  523. return NULL;
  524. while (*pinf != 0 || *(pinf + 1) == ' ')
  525. pinf++;
  526. return *++pinf ? pinf : NULL;
  527. }
  528. /* int FAR PASCAL infLineCount(pinf)
  529. *
  530. * Given a section from SETUP.INF, returns the number of lines in the section
  531. *
  532. * ENTRY:
  533. *
  534. * pinf : pointer to a section from SETUP.INF
  535. *
  536. * EXIT: returns line count
  537. *
  538. */
  539. int infLineCount(PINF pinf)
  540. {
  541. int n = 0;
  542. for (n=0; pinf; pinf = infNextLine(pinf))
  543. n++;
  544. return n;
  545. }