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.

691 lines
17 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 LPSTR pBuf;
  40. static PINF pInf;
  41. static UINT iBuf;
  42. static UINT iInf;
  43. /* Globaly used pointers to non-translatable text strings. */
  44. extern TCHAR *pszPATH;
  45. /* Local prototypes */
  46. BOOL multifields(PINF);
  47. static TCHAR 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(TCHAR c)
  61. {
  62. if (!pInf)
  63. return;
  64. pInf[iInf++] = c;
  65. }
  66. static void MODIFYC(TCHAR c)
  67. {
  68. if (!pInf)
  69. return;
  70. pInf[iInf++ - 1] = c;
  71. }
  72. static TCHAR 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. TCHAR 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*sizeof(TCHAR)); // 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 TEXT('['):
  117. inSectionName = TRUE;
  118. PUTC(c);
  119. break;
  120. case TEXT(']'):
  121. if (inSectionName) {
  122. if (LASTC() == TEXT(' ')) {
  123. MODIFYC(c);
  124. } else {
  125. PUTC(c);
  126. }
  127. inSectionName = FALSE;
  128. } else {
  129. PUTC(c);
  130. }
  131. break;
  132. case TEXT('\r'): /* ignore '\r' */
  133. break;
  134. case TEXT('\n'):
  135. for (; ISWHITE(c); c = GETC(fh))
  136. ;
  137. if (c != TEXT(';'))
  138. PUTC(0); /* all lines end in a \0 */
  139. if (c == TEXT('[')) {
  140. PUTC(0); /* all sections end with \0\0 */
  141. }
  142. fQuote = FALSE;
  143. goto loop;
  144. break;
  145. case TEXT('\t'):
  146. case TEXT(' '):
  147. if (inSectionName) {
  148. if (LASTC() != TEXT(' ') && LASTC() != TEXT(']'))
  149. PUTC(TEXT(' '));
  150. } else {
  151. if (fQuote)
  152. PUTC(c);
  153. }
  154. break;
  155. case TEXT('"'):
  156. fQuote = !fQuote;
  157. PUTC(c);
  158. break;
  159. case TEXT(';'):
  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(LPTSTR szInf)
  188. {
  189. TCHAR 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 = HandleToUlong(CreateFile(szInf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
  201. }
  202. /*
  203. * Next try destination path\system32. for win half.
  204. */
  205. if (fh == -1) {
  206. lstrcpy(szBuf, szSetupPath);
  207. catpath(szBuf, TEXT("system32"));
  208. catpath(szBuf, szInf);
  209. fh = HandleToUlong(CreateFile(szBuf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
  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 = HandleToUlong(CreateFile(szBuf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
  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 LPTSTR 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_PTR FindSection(PINF pInf, LPTSTR 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++ == TEXT('['))
  266. {
  267. fFound = !_wcsnicmp(pszSect, pch, nLen) && pch[nLen] == TEXT(']');
  268. }
  269. /*
  270. * go to the next line, dont forget to skip over \0 and \0\0
  271. */
  272. while (*pch != EOF && *pch != TEXT('\0'))
  273. pch++;
  274. while (*pch == 0)
  275. pch++;
  276. }
  277. return((fFound && *pch != TEXT('[') && *pch != EOF) ? pch - pInf : 0);
  278. }
  279. /* LONG fnGetDataString(npszData,szDataStr,szBuf,cchBuf)
  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. * szDataStr : pointer to key word to look for (welcome in example above.)
  293. * szBuf : pointer to a buffer to hold result
  294. * cchBuf : size of destination buffer (szBuf) in characters.
  295. * length must be large enough to hold all of the
  296. * text including the null terminator.
  297. *
  298. * EXIT: returns ERROR_SUCCESS if successful, ERROR_NOT_FOUND or ERROR_INSUFFICIENT_BUFFER if failure.
  299. *
  300. */
  301. LONG fnGetDataString(PINF npszData, LPTSTR szDataStr, LPTSTR szBuf, size_t cchBuf)
  302. {
  303. LPTSTR szBufOrig = szBuf;
  304. int len = lstrlen(szDataStr);
  305. while (npszData)
  306. {
  307. if (!_wcsnicmp(npszData,szDataStr,len)) // looking for correct prof.
  308. {
  309. npszData += len; // found !, look past prof str.
  310. while (ISWHITE(*npszData)) // pull out the garbage.
  311. npszData++;
  312. if (*npszData == EQUAL) // Now we have what were looking for !
  313. {
  314. npszData++;
  315. if (!multifields(npszData) )
  316. {
  317. while (ISWHITE(*npszData) || ISNOISE(*npszData))
  318. npszData++;
  319. while (*npszData)
  320. {
  321. *szBuf++ = *npszData++;
  322. cchBuf--;
  323. ASSERT( cchBuf > 0 );
  324. if( cchBuf <= 0 )
  325. {
  326. *szBufOrig = TEXT('\0');
  327. return ERROR_INSUFFICIENT_BUFFER;
  328. }
  329. }
  330. /*
  331. * remove trailing spaces, and those pesky ()'s
  332. */
  333. while (ISWHITE(szBuf[-1]) || ISNOISE(szBuf[-1]))
  334. szBuf--;
  335. *szBuf = 0;
  336. return ERROR_SUCCESS;
  337. }
  338. else
  339. {
  340. while (*npszData)
  341. {
  342. *szBuf++ = *npszData++;
  343. cchBuf--;
  344. ASSERT( cchBuf > 0 );
  345. if( cchBuf <= 0 )
  346. {
  347. *szBufOrig = TEXT('\0');
  348. return ERROR_INSUFFICIENT_BUFFER;
  349. }
  350. }
  351. *szBuf = TEXT('\0');
  352. return ERROR_SUCCESS;
  353. }
  354. }
  355. }
  356. npszData = infNextLine(npszData);
  357. }
  358. *szBuf = 0;
  359. return ERROR_NOT_FOUND;
  360. }
  361. /* PINF FAR PASCAL infSetDefault(pinf)
  362. *
  363. * Sets the default INF file
  364. *
  365. * ENTRY:
  366. * pinf : inf file to be new default
  367. *
  368. * EXIT: returns old default
  369. *
  370. */
  371. PINF infSetDefault(PINF pinf)
  372. {
  373. PINF pinfT;
  374. pinfT = pinfDefault;
  375. pinfDefault = pinf;
  376. return pinfT;
  377. }
  378. /* PINF FAR PASCAL infFindSection(pinf,szSection)
  379. *
  380. * Reads a entire section into memory and returns a pointer to it
  381. *
  382. * ENTRY:
  383. * pinf : inf file to search for section
  384. * szSection : section name to read
  385. *
  386. * EXIT: returns pointer to section, NULL if error
  387. *
  388. */
  389. PINF infFindSection(PINF pinf, LPTSTR szSection)
  390. {
  391. UINT_PTR pos;
  392. if (pinf == NULL)
  393. pinf = pinfDefault;
  394. pos = FindSection(pinf, szSection);
  395. return pos ? pinf + pos : NULL;
  396. }
  397. /* LONG FAR PASCAL infGetProfileString(szSection,szItem,szBuf,cchBuf)
  398. *
  399. * Reads a single string from a section in SETUP.INF
  400. *
  401. * [section]
  402. * item = string
  403. *
  404. * ENTRY:
  405. * szSection : pointer to section name to read.
  406. * szItem : pointer to item name to read
  407. * szBuf : pointer to a buffer to hold result
  408. * cchBuf : size of destination buffer (szBuf) in characters.
  409. * length must be large enough to hold all of the
  410. * text including the null terminator.
  411. *
  412. * EXIT: returns ERROR_SUCCESS if successful, ERROR_NOT_FOUND or ERROR_INSUFFICIENT_BUFFER if failure.
  413. *
  414. */
  415. LONG infGetProfileString(PINF pinf, LPTSTR szSection,LPTSTR szItem,LPTSTR szBuf,size_t cchBuf)
  416. {
  417. PINF pSection;
  418. pSection = infFindSection(pinf,szSection);
  419. if (pSection )
  420. return fnGetDataString(pSection,szItem,szBuf,cchBuf);
  421. else
  422. *szBuf = 0;
  423. return ERROR_NOT_FOUND;
  424. }
  425. /* LONG FAR PASCAL infParseField(szData,n,szBuf,cchBuf)
  426. *
  427. * Given a line from SETUP.INF, will extract the nth field from the string
  428. * fields are assumed separated by comma's. Leading and trailing spaces
  429. * are removed.
  430. *
  431. * ENTRY:
  432. *
  433. * szData : pointer to line from SETUP.INF
  434. * n : field to extract. ( 1 based )
  435. * 0 is field before a '=' sign
  436. * szBuf : pointer to buffer to hold extracted field
  437. * cchBuf : size of destination buffer (szBuf) in characters.
  438. * length must be large enough to hold all of the
  439. * text including the null terminator.
  440. *
  441. * EXIT: returns ERROR_SUCCESS if successful,
  442. * ERROR_INVALID_PARAMETER, ERROR_NOT_FOUND or ERROR_INSUFFICIENT_BUFFER if failure.
  443. *
  444. */
  445. LONG infParseField(PINF szData, int n, LPTSTR szBuf, size_t cchBuf)
  446. {
  447. BOOL fQuote = FALSE;
  448. PINF pch;
  449. LPTSTR ptr;
  450. ASSERT(szData != NULL);
  451. ASSERT(szBuf != NULL);
  452. if (!szData || !szBuf)
  453. {
  454. if( szBuf )
  455. {
  456. szBuf[0] = 0; // make szBuf empty
  457. }
  458. return ERROR_INVALID_PARAMETER;
  459. }
  460. /*
  461. * find the first separator
  462. */
  463. for (pch=szData; *pch && !ISSEP(*pch); pch++) {
  464. if ( *pch == QUOTE )
  465. fQuote = !fQuote;
  466. }
  467. if (n == 0 && *pch != TEXT('='))
  468. {
  469. szBuf[0] = 0; // make szBuf empty
  470. return ERROR_NOT_FOUND;
  471. }
  472. if (n > 0 && *pch == TEXT('=') && !fQuote)
  473. szData = ++pch;
  474. /*
  475. * locate the nth comma, that is not inside of quotes
  476. */
  477. fQuote = FALSE;
  478. while (n > 1)
  479. {
  480. while (*szData)
  481. {
  482. if (!fQuote && ISSEP(*szData))
  483. break;
  484. if (*szData == QUOTE)
  485. fQuote = !fQuote;
  486. szData++;
  487. }
  488. if (!*szData) {
  489. szBuf[0] = 0; // make szBuf empty
  490. return ERROR_NOT_FOUND;
  491. }
  492. szData++;
  493. n--;
  494. }
  495. /*
  496. * now copy the field to szBuf
  497. */
  498. while (ISWHITE(*szData))
  499. szData++;
  500. fQuote = FALSE;
  501. ptr = szBuf; // fill output buffer with this
  502. while (*szData)
  503. {
  504. if (*szData == QUOTE)
  505. fQuote = !fQuote;
  506. else if (!fQuote && ISSEP(*szData))
  507. break;
  508. else
  509. {
  510. *ptr++ = *szData;
  511. cchBuf--;
  512. ASSERT( cchBuf > 0 );
  513. if( cchBuf <= 0 )
  514. {
  515. *szBuf = TEXT('\0');
  516. return ERROR_INSUFFICIENT_BUFFER;
  517. }
  518. }
  519. szData++;
  520. }
  521. /*
  522. * remove trailing spaces, and those pesky ()'s
  523. */
  524. while ((ptr > szBuf) && (ISWHITE(ptr[-1]) || ISNOISE(ptr[-1])))
  525. ptr--;
  526. *ptr = 0;
  527. return ERROR_SUCCESS;
  528. }
  529. /* BOOL multifields(LPTSTR npszData);
  530. *
  531. * Given a line line from mmdriver.inf that was after a profile
  532. * string this function will determine if that line has more than one
  533. * field. ie. Fields are seperated by commas that are NOT contained between
  534. * quotes.
  535. *
  536. * ENYRY:
  537. *
  538. * npszData : a line from setup.inf Example "xyz adapter",1:foobar.drv
  539. *
  540. * EXIT: This function will return TRUE if the line containes more than
  541. * one field, ie the function would return TRUE for the example line
  542. * shown above.
  543. *
  544. */
  545. BOOL multifields(PINF npszData)
  546. {
  547. BOOL fQuote = FALSE;
  548. while (*npszData)
  549. {
  550. if (!fQuote && ISSEP(*npszData))
  551. return TRUE;
  552. if (*npszData == QUOTE)
  553. fQuote = !fQuote;
  554. npszData++;
  555. }
  556. return FALSE;
  557. }
  558. /* LPTSTR FAR PASCAL infNextLine(sz)
  559. *
  560. * Given a line from SETUP.INF, advance to the next line. will skip past the
  561. * ending NULL character checking for end of buffer \0\0
  562. *
  563. * ENTRY:
  564. *
  565. * sz : pointer to line from a SETUP.INF section
  566. *
  567. * EXIT: returns pointer to next line if successful, NULL if failure.
  568. *
  569. */
  570. PINF infNextLine(PINF pinf)
  571. {
  572. if (!pinf)
  573. return NULL;
  574. while (*pinf != 0 || *(pinf + 1) == TEXT(' '))
  575. pinf++;
  576. return *++pinf ? pinf : NULL;
  577. }
  578. /* int FAR PASCAL infLineCount(pinf)
  579. *
  580. * Given a section from SETUP.INF, returns the number of lines in the section
  581. *
  582. * ENTRY:
  583. *
  584. * pinf : pointer to a section from SETUP.INF
  585. *
  586. * EXIT: returns line count
  587. *
  588. */
  589. int infLineCount(PINF pinf)
  590. {
  591. int n = 0;
  592. for (n=0; pinf; pinf = infNextLine(pinf))
  593. n++;
  594. return n;
  595. }