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.

668 lines
22 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. escpeinf.c
  5. Abstract:
  6. This module filters an inf for use by the ESCAPE tool. Default file
  7. security can be set in the inx file using wildcard rules, and this
  8. program expands them, creating a valid file for ESCAPE. This is
  9. necessary because ESCAPE does not support wildcards in the file section
  10. See below for more information.
  11. Note: ESCAPE was the proposed name of the Security Configuration Engine when this
  12. was written, but that name too was dropped. They still haven't come up with
  13. a good name for it.
  14. Author:
  15. Sandy Coyne (scoyne) February 29, 2000
  16. Revision History:
  17. --*/
  18. /*
  19. Usage: escpeinf.exe <U|C> <codepage> <input file> <output file> <layout.inf>
  20. Parameter info is printed when you run the program without all the right arguments
  21. layout.inf is the system-wide layout.inf, already built for the local
  22. language, arch., etc.
  23. The input file to this program consists of an inf, already sent through
  24. the filters for architecture, language and product. This inf is an input
  25. file for ESCAPE, with one exception: In the [File Security] section, some
  26. entries may have wildcards for filenames. Following those lines, if
  27. desired, is a list of files that should be excluded from matching that
  28. wildcard. This list is in the form of exception lines.
  29. Example:
  30. [File Security]
  31. "%SystemDirectory%\*",2,"D:P(A;;GRGX;;;BU)(A;;GRGX;;;PU)(A;;GA;;;BA)(A;;GA;;;SY)"
  32. Exception="*.ini"
  33. Exception="config.nt"
  34. This wildcard line will be replaced with an enumeration of all matching files
  35. that are copied by text-mode setup, as specified by the listing in layout.inf
  36. */
  37. #include <windows.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <tchar.h>
  41. #include <string.h>
  42. #include <locale.h>
  43. #include <mbctype.h>
  44. #include <inflib.h>
  45. #include <sputils.h>
  46. #include <wild.c>
  47. // Define program result codes (returned from main()).
  48. #define SUCCESS 0
  49. #define FAILURE 1
  50. #define MAX_INF_LINE_LENGTH 260
  51. #define MAX_EXCEPTIONS 256
  52. #define ESCPEINF_VERSION "1.6"
  53. //#define ESCPEINF_DEBUG
  54. enum {
  55. UPGRADE,
  56. CLEAN_INSTALL
  57. } GlobalMode;
  58. typedef struct _EXCEPTIONS {
  59. TCHAR s[MAX_INF_LINE_LENGTH];
  60. } EXCEPTIONS;
  61. typedef struct _MYPARAM {
  62. FILE *OutputFile;
  63. EXCEPTIONS *ExceptionList;
  64. DWORD Num;
  65. PTSTR WildCard,
  66. RealPath,
  67. LayoutPath,
  68. SecurityString;
  69. } MYPARAM, *PMYPARAM;
  70. BOOL ProcessFileSecuritySection(FILE *InputFile, FILE *OutputFile,
  71. PLAYOUT_CONTEXT LayoutContexta);
  72. BOOL GetFields(PTSTR InfLine, PTSTR FileName, DWORD *Num, PTSTR SecurityString);
  73. void ExpandWildCard(PTSTR FileName, DWORD Num, PTSTR SecurityString,
  74. EXCEPTIONS ExceptionList[], FILE *OutputFile,
  75. PLAYOUT_CONTEXT LayoutContext);
  76. void FindExceptions(FILE *InputFile, EXCEPTIONS ExceptionList[]);
  77. void PrintUsage(LPTSTR FileName)
  78. {
  79. _ftprintf(stderr, TEXT("ESCAPE Inf file pre-processor, version %s\n"),
  80. TEXT(ESCPEINF_VERSION));
  81. _ftprintf(stderr, TEXT("\tFor Microsoft internal use only. "));
  82. _ftprintf(stderr, TEXT("Contact Sandy Coyne with questions.\n"));
  83. _ftprintf(stderr,
  84. TEXT("Usage: %s <U|C> <codepage> <input file> <output file> <layout.inf>\n"),
  85. FileName);
  86. _ftprintf(stderr, TEXT("\tU = Upgrade\n"));
  87. _ftprintf(stderr, TEXT("\tC = Clean Install\n"));
  88. _ftprintf(stderr,
  89. TEXT("\t<codepage> specifies the codepage to use when accessing input and\n"));
  90. _ftprintf(stderr,
  91. TEXT("\t\toutput files. Translation of layout.inf is not affected by\n"));
  92. _ftprintf(stderr,
  93. TEXT("\t\tthis option. You may specify \"none\" to open the input\n"));
  94. _ftprintf(stderr,
  95. TEXT("\t\tand output files as Unicode files with no codepage translation.\n"));
  96. _ftprintf(stderr, TEXT("\tAll fields are required.\n"));
  97. }
  98. int __cdecl _tmain(IN int argc, IN LPTSTR argv[])
  99. {
  100. FILE *InputFile,
  101. *OutputFile;
  102. LPTSTR LocaleString;
  103. TCHAR InfLine[MAX_INF_LINE_LENGTH],
  104. CodePage[10];
  105. PLAYOUT_CONTEXT LayoutContext;
  106. BOOL fUnicodeIO;
  107. int result = FAILURE;
  108. if(!pSetupInitializeUtils()) {
  109. _ftprintf(stderr, TEXT("Initialize failed\n"));
  110. return FAILURE;
  111. }
  112. // Print Usage information
  113. if (argc != 6)
  114. {
  115. PrintUsage(argv[0]);
  116. goto fail;
  117. }
  118. if (_tcsicmp(argv[1], TEXT("U")) == 0)
  119. {
  120. GlobalMode = UPGRADE;
  121. }
  122. else if (_tcsicmp(argv[1], TEXT("C")) == 0)
  123. {
  124. GlobalMode = CLEAN_INSTALL;
  125. }
  126. else
  127. {
  128. PrintUsage(argv[0]);
  129. goto fail;
  130. }
  131. if (_tcsicmp(argv[2], TEXT("None")) == 0)
  132. {
  133. fUnicodeIO = TRUE;
  134. #ifdef ESCPEINF_DEBUG
  135. _ftprintf(stderr, TEXT("Using Unicode I/O\n"));
  136. #endif
  137. }
  138. else
  139. {
  140. _stprintf(CodePage, TEXT(".%.7s"), argv[2]);
  141. LocaleString = _tsetlocale(LC_ALL, CodePage);
  142. if (LocaleString == NULL)
  143. {
  144. _ftprintf(stderr, TEXT("Invalid CodePage: \"%s\"\n"), argv[2]);
  145. #ifdef ESCPEINF_DEBUG
  146. _ftprintf(stderr, TEXT("Invalid argument to setlocale: \"%s\"\n"), CodePage);
  147. #endif
  148. goto fail;
  149. }
  150. else
  151. {
  152. #ifdef ESCPEINF_DEBUG
  153. _ftprintf(stderr, TEXT("Locale set to: \"%s\"\n"), LocaleString);
  154. #endif
  155. fUnicodeIO = FALSE;
  156. }
  157. }
  158. // Begin to Open Input, Output and Layout files
  159. if (fUnicodeIO)
  160. {
  161. InputFile = _tfopen(argv[3], TEXT("rb"));
  162. }
  163. else
  164. {
  165. InputFile = _tfopen(argv[3], TEXT("rt"));
  166. }
  167. if (InputFile == NULL)
  168. {
  169. _ftprintf(stderr, TEXT("Error opening Input file: %s\n"), argv[3]);
  170. goto fail;
  171. }
  172. #ifdef ESCPEINF_DEBUG
  173. _ftprintf(stderr, TEXT("Opened Input file: %s\n"), argv[3]);
  174. #endif
  175. rewind(InputFile);
  176. if (fUnicodeIO)
  177. {
  178. OutputFile = _tfopen(argv[4], TEXT("wb"));
  179. }
  180. else
  181. {
  182. OutputFile = _tfopen(argv[4], TEXT("wt"));
  183. }
  184. if (OutputFile == NULL)
  185. {
  186. _ftprintf(stderr, TEXT("Error opening Output file: %s\n"), argv[4]);
  187. fclose(InputFile);
  188. goto fail;
  189. }
  190. #ifdef ESCPEINF_DEBUG
  191. _ftprintf(stderr, TEXT("Opened Output file: %s\n"), argv[4]);
  192. #endif
  193. LayoutContext = BuildLayoutInfContext(argv[5], LAYOUTPLATFORMS_ALL, 0);
  194. if (LayoutContext == NULL)
  195. {
  196. _ftprintf(stderr, TEXT("Error opening Layout file: %s\n"), argv[5]);
  197. _ftprintf(stderr, TEXT("Did you remember to specify a path to the file\n"));
  198. fclose(InputFile); fclose(OutputFile);
  199. goto fail;
  200. }
  201. else
  202. {
  203. #ifdef ESCPEINF_DEBUG
  204. _ftprintf(stderr, TEXT("Opened Layout file: %s\n"), argv[5]);
  205. #endif
  206. }
  207. // Input, Output and Layout files are open
  208. while ((_fgetts(InfLine, MAX_INF_LINE_LENGTH, InputFile)) != NULL)
  209. {
  210. _fputts(InfLine, OutputFile);
  211. if (!_tcscmp(InfLine, TEXT("[File Security]\n")))
  212. if (!ProcessFileSecuritySection(InputFile, OutputFile,
  213. LayoutContext))
  214. {
  215. // If this happens, ProcessFileSecuritySection() has already
  216. // printed an error.
  217. fclose(InputFile); fclose(OutputFile);
  218. CloseLayoutInfContext(LayoutContext);
  219. goto fail;
  220. }
  221. }
  222. if (!feof(InputFile))
  223. {
  224. _ftprintf(stderr, TEXT("Error: Did not reach Input EOF.\n"));
  225. fclose(InputFile); fclose(OutputFile);
  226. CloseLayoutInfContext(LayoutContext);
  227. goto fail;
  228. }
  229. fclose(InputFile);
  230. fclose(OutputFile);
  231. CloseLayoutInfContext(LayoutContext);
  232. #ifdef ESCPEINF_DEBUG
  233. _ftprintf(stderr, TEXT("escpeinf.exe completed successfully\n"));
  234. #endif
  235. result = SUCCESS;
  236. fail:
  237. pSetupUninitializeUtils();
  238. return result;
  239. }
  240. BOOL CALLBACK MyCallback(IN PLAYOUT_CONTEXT Context,
  241. IN PCTSTR FileName,
  242. IN PFILE_LAYOUTINFORMATION LayoutInformation,
  243. IN PVOID ExtraData,
  244. IN UINT ExtraDataSize,
  245. IN OUT DWORD_PTR vpParam)
  246. {
  247. static PMYPARAM Param;
  248. static BOOL fIsException = FALSE;
  249. static int i = 0;
  250. static TCHAR FileName_l[MAX_PATH],
  251. TargetFileName_l[MAX_PATH];
  252. i = 0;
  253. fIsException = FALSE;
  254. if (vpParam)
  255. Param = (PMYPARAM)vpParam;
  256. // Quit now if we don't need to worry about this file at all.
  257. if ((GlobalMode == UPGRADE) &&
  258. (LayoutInformation->UpgradeDisposition == 3))
  259. return TRUE;
  260. if ((GlobalMode == CLEAN_INSTALL) &&
  261. (LayoutInformation->CleanInstallDisposition == 3))
  262. return TRUE;
  263. // Quit now if the names are too long to be processed.
  264. // This should never happen with layout.inf
  265. if ((_tcslen(FileName) >= MAX_PATH) ||
  266. (_tcslen(LayoutInformation->TargetFileName) >= MAX_PATH))
  267. return TRUE;
  268. // Make a local copy for lowercasing:
  269. _tcsncpy(FileName_l, FileName, MAX_PATH);
  270. _tcsncpy(TargetFileName_l, LayoutInformation->TargetFileName, MAX_PATH);
  271. // Just to be safe:
  272. FileName_l[MAX_PATH-1] = TEXT('\0');
  273. TargetFileName_l[MAX_PATH-1] = TEXT('\0');
  274. // Since wildcard compares are case sensitive, I lowercase everything
  275. // before comparing. Wildcard compares happen between the two filename
  276. // variables modified here, WildCard, and ExceptionList. WildCard and
  277. // ExceptionList were previouslt lowercased.
  278. _tcslwr(FileName_l);
  279. _tcslwr(TargetFileName_l);
  280. if (_tcslen(TargetFileName_l) > 0) // Do we use the long name?
  281. {
  282. if (_tcsicmp(Param->LayoutPath, LayoutInformation->Directory) == 0)
  283. { // Then it's a file in the right directory
  284. if (IsNameInExpressionPrivate(Param->WildCard, TargetFileName_l))
  285. { // Then it matches our wildcard
  286. while ((_tcslen(Param->ExceptionList[i].s) > 0) && !fIsException)
  287. { // Checking to see if it's an exception...
  288. if (IsNameInExpressionPrivate(Param->ExceptionList[i].s,
  289. TargetFileName_l))
  290. {
  291. fIsException = TRUE; // This must be initialized FALSE
  292. }
  293. i += 1;
  294. }
  295. if (!fIsException)
  296. { // Then we actually want to put it in our output
  297. #ifdef ESCPEINF_DEBUG
  298. _ftprintf(stderr, TEXT("Match: %s(%s) in %s\n"),
  299. FileName, LayoutInformation->TargetFileName,
  300. LayoutInformation->Directory);
  301. #endif
  302. _ftprintf(Param->OutputFile, TEXT("\"%s\\%s\",%d,%s\n"),
  303. Param->RealPath,
  304. LayoutInformation->TargetFileName, Param->Num,
  305. Param->SecurityString);
  306. }
  307. }
  308. }
  309. }
  310. else // We use the short name
  311. {
  312. if (_tcsicmp(Param->LayoutPath, LayoutInformation->Directory) == 0)
  313. { // Then it's a file in the right directory
  314. if (IsNameInExpressionPrivate(Param->WildCard, FileName_l))
  315. { // Then it matches our wildcard
  316. while ((_tcslen(Param->ExceptionList[i].s) > 0) && !fIsException)
  317. { // Checking to see if it's an exception...
  318. if (IsNameInExpressionPrivate(Param->ExceptionList[i].s,
  319. FileName_l))
  320. {
  321. fIsException = TRUE; // This must be initialized FALSE
  322. }
  323. i += 1;
  324. }
  325. if (!fIsException)
  326. { // Then we actually want to put it in our output
  327. #ifdef ESCPEINF_DEBUG
  328. _ftprintf(stderr, TEXT("Match: %s in %s\n"),
  329. FileName, LayoutInformation->Directory);
  330. #endif
  331. _ftprintf(Param->OutputFile, TEXT("\"%s\\%s\",%d,%s\n"),
  332. Param->RealPath, FileName, Param->Num,
  333. Param->SecurityString);
  334. }
  335. }
  336. }
  337. }
  338. return TRUE;
  339. }
  340. BOOL ProcessFileSecuritySection(FILE *InputFile, FILE *OutputFile,
  341. PLAYOUT_CONTEXT LayoutContext)
  342. {
  343. TCHAR InfLine[MAX_INF_LINE_LENGTH],
  344. FileName[MAX_INF_LINE_LENGTH],
  345. SecurityString[MAX_INF_LINE_LENGTH];
  346. BOOL fValidFields;
  347. DWORD Num;
  348. int i;
  349. EXCEPTIONS ExceptionList[MAX_EXCEPTIONS];
  350. #ifdef ESCPEINF_DEBUG
  351. _ftprintf(stderr, TEXT("Found [File Security] section.\n"));
  352. #endif
  353. while ((_fgetts(InfLine, MAX_INF_LINE_LENGTH, InputFile)) != NULL)
  354. {
  355. if (GetFields(InfLine, FileName, &Num, SecurityString) &&
  356. DoesNameContainWildCards(FileName))
  357. { // We found a line containing proper formatting and a wildcard
  358. // in the filename
  359. #ifdef ESCPEINF_DEBUG
  360. _ftprintf(stderr, TEXT("Wildcard line: %s"), InfLine);
  361. #endif
  362. // First find the exceptions to the wildcard
  363. FindExceptions(InputFile, ExceptionList);
  364. ExpandWildCard(FileName, Num, SecurityString, ExceptionList,
  365. OutputFile, LayoutContext);
  366. }
  367. else
  368. {
  369. _fputts(InfLine, OutputFile);
  370. if (_tcsncmp(InfLine, TEXT("["), 1) == 0)
  371. {
  372. #ifdef ESCPEINF_DEBUG
  373. _ftprintf(stderr, TEXT("End of File Security section.\n"));
  374. #endif
  375. return TRUE;
  376. }
  377. }
  378. }
  379. return TRUE; // No Error
  380. }
  381. // GetFields assumes the input line is in this format:
  382. // "filename",number,"securitystring"\n
  383. // It extracts the filename and stores it in FileName. The quotes are removed
  384. // from filename. It extracts and stores the number and security string if
  385. // the filename is found. Quotes are not stripped from the security string.
  386. // On error, it sets FileName to zero length, and returns FALSE.
  387. BOOL GetFields(PTSTR InfLine, PTSTR FileName, DWORD *Num, PTSTR SecurityString)
  388. {
  389. int i = 0; // Pointer to current location in FileName
  390. // Leave now if the line does not contain a filename
  391. if ((InfLine[0] == (TCHAR)'[') ||
  392. (InfLine[0] == (TCHAR)'\n') ||
  393. (InfLine[0] == (TCHAR)';'))
  394. {
  395. FileName[0] = (TCHAR)'\0'; // Set the end-of-string NULL marker to clear the string
  396. return FALSE;
  397. }
  398. // Check if line starts with a quotation mark
  399. if (InfLine[0] == (TCHAR)'\"')
  400. {
  401. // Copy everything until the next quotation mark
  402. while ((InfLine[i+1] != (TCHAR)'\"') && (InfLine[i+1] != (TCHAR)'\0'))
  403. {
  404. FileName[i] = InfLine[i+1];
  405. i += 1;
  406. }
  407. FileName[i] = (TCHAR)'\0'; // Set the end-of-string NULL marker
  408. i += 1; // So we can use i without the +1 to access InfLine from now on
  409. }
  410. else // if the filename is not in quotes
  411. {
  412. FileName[0] = (TCHAR)'\0'; // Set the end-of-string NULL marker to clear the string
  413. return FALSE;
  414. }
  415. // It is posible that we left the above while loop because of premature end-of-line condtion.
  416. // If this is the case, clear the filename string and return.
  417. if (InfLine[i] == (TCHAR)'\0')
  418. {
  419. #ifdef ESCPEINF_DEBUG
  420. _ftprintf(stderr, TEXT("Reached End-of-Line without finding a filename\n"));
  421. _ftprintf(stderr, TEXT("Problem line is <%s>\n"), InfLine);
  422. _ftprintf(stderr, TEXT("Problem filename is <%s>\n"), FileName);
  423. #endif
  424. FileName[0] = (TCHAR)'\0'; // Set the end-of-string NULL marker to clear the string
  425. return FALSE;
  426. }
  427. else i++; // Once we know that we aren't at the end-of-string, we can do this safely.
  428. // Now, however, we may be pointing to a zero-length string.
  429. if (_tcslen(FileName) <= 3)
  430. {
  431. #ifdef ESCPEINF_DEBUG
  432. _ftprintf(stderr, TEXT("Unexpected Result: Filename \"%s\" is only %d characters.\n"), FileName, i);
  433. #endif
  434. return FALSE;
  435. }
  436. #ifdef ESCPEINF_DEBUG
  437. //_ftprintf(stderr, TEXT("Found filename : %s\n"), FileName);
  438. #endif
  439. // Read the other two fields. If we got this far, we must have found a valid filename,
  440. // so we just assume that the other two are there.
  441. if (_stscanf(&InfLine[i], TEXT(",%ld,%s"), Num, SecurityString) != 2)
  442. { // then there was an error
  443. #ifdef ESCPEINF_DEBUG
  444. _ftprintf(stderr, TEXT("Error reading Num and Security String from line.\n"));
  445. _ftprintf(stderr, TEXT("Problem line is: %s\n"), &InfLine[i]);
  446. #endif
  447. FileName[0] = (TCHAR)'\0'; // Set the end-of-string NULL marker to clear the string
  448. return FALSE;
  449. }
  450. #ifdef ESCPEINF_DEBUG
  451. //_ftprintf(stderr, TEXT("Found rest of line : %lu,%s\n"), *Num, SecurityString);
  452. #endif
  453. return TRUE;
  454. }
  455. void ExpandWildCard(PTSTR FileName, DWORD Num, PTSTR SecurityString,
  456. EXCEPTIONS ExceptionList[], FILE *OutputFile,
  457. PLAYOUT_CONTEXT LayoutContext)
  458. {
  459. MYPARAM Param;
  460. int PathPos = 0;
  461. int NamePos = 0;
  462. int LastSlash = 0;
  463. TCHAR WildCard[MAX_INF_LINE_LENGTH],
  464. RealPath[MAX_INF_LINE_LENGTH],
  465. LayoutPath[MAX_INF_LINE_LENGTH];
  466. if (_tcslen(FileName) >= MAX_INF_LINE_LENGTH)
  467. return; // This should never happen, but we're being safe.
  468. while (FileName[NamePos] != (TCHAR)'\0')
  469. {
  470. if (FileName[NamePos] == (TCHAR)'\\')
  471. {
  472. LastSlash = NamePos;
  473. }
  474. NamePos += 1;
  475. }
  476. if (NamePos == (LastSlash + 1))
  477. return; // What? No filename? This should never happen.
  478. _tcsncpy(RealPath, FileName, LastSlash);
  479. RealPath[LastSlash] = (TCHAR)'\0';
  480. _tcscpy(WildCard, &FileName[LastSlash + 1]);
  481. _tcslwr(WildCard);
  482. #ifdef ESCPEINF_DEBUG
  483. _ftprintf(stderr, TEXT("Looking up Wildcard: %s\nin: %s\n"),
  484. WildCard, RealPath);
  485. #endif
  486. if (_tcsnicmp(RealPath, TEXT("%SystemDirectory%"), 17) == 0)
  487. {
  488. _tcscpy(LayoutPath, TEXT("System32"));
  489. _tcscpy(&LayoutPath[8], &RealPath[17]);
  490. }
  491. else if (_tcsnicmp(RealPath, TEXT("%SystemDir%"), 11) == 0)
  492. {
  493. _tcscpy(LayoutPath, TEXT("System32"));
  494. _tcscpy(&LayoutPath[8], &RealPath[11]);
  495. }
  496. else if (_tcsnicmp(RealPath, TEXT("%SystemRoot%"), 12) == 0)
  497. {
  498. if (LastSlash == 12)
  499. _tcscpy(LayoutPath, TEXT("\\"));
  500. else
  501. _tcscpy(LayoutPath, &RealPath[13]);
  502. }
  503. else
  504. {
  505. _ftprintf(stderr, TEXT("Path is unlikely to be in Layout.inf: %s\n"),
  506. RealPath);
  507. _tcscpy(LayoutPath, RealPath);
  508. }
  509. #ifdef ESCPEINF_DEBUG
  510. _ftprintf(stderr, TEXT("Path in Layout.inf terms is: %s\n"), LayoutPath);
  511. #endif
  512. Param.OutputFile = OutputFile;
  513. Param.ExceptionList = ExceptionList;
  514. Param.Num = Num;
  515. Param.WildCard = WildCard;
  516. Param.RealPath = RealPath,
  517. Param.LayoutPath = LayoutPath;
  518. Param.SecurityString= SecurityString;
  519. EnumerateLayoutInf(LayoutContext, MyCallback, (DWORD_PTR)&Param);
  520. return;
  521. }
  522. void FindExceptions(FILE *InputFile, EXCEPTIONS ExceptionList[])
  523. {
  524. long FilePosition;
  525. int NumExceptions = 0,
  526. i;
  527. TCHAR InfLine[MAX_INF_LINE_LENGTH];
  528. do
  529. {
  530. i = 0;
  531. FilePosition = ftell(InputFile); // Save file pointer
  532. if (_fgetts(InfLine, MAX_INF_LINE_LENGTH, InputFile) != NULL)
  533. {
  534. if ((_tcsnicmp(InfLine, TEXT("Exception=\""), 11) == 0) ||
  535. (_tcsnicmp(InfLine, TEXT("Exception:\""), 11) == 0))
  536. {
  537. while ((InfLine[i+11] != (TCHAR)'\"') &&
  538. (InfLine[i+11] != (TCHAR)'\0'))
  539. {
  540. ExceptionList[NumExceptions].s[i] = InfLine[i+11];
  541. i += 1;
  542. }
  543. ExceptionList[NumExceptions].s[i] = (TCHAR)'\0';
  544. _tcslwr(ExceptionList[NumExceptions].s);
  545. #ifdef ESCPEINF_DEBUG
  546. _ftprintf(stderr, TEXT("Exception found: %s\n"),
  547. ExceptionList[NumExceptions].s);
  548. #endif
  549. if (InfLine[i+11] == (TCHAR)'\0')
  550. { // then we hit end of line without closing our quotes
  551. _ftprintf(stderr, TEXT("Warning: Invalid Exception line.\n"));
  552. _ftprintf(stderr, TEXT("Problem line is: %s\n"), InfLine);
  553. }
  554. else NumExceptions += 1;
  555. }
  556. }
  557. }
  558. while ((i > 0) && (NumExceptions < (MAX_EXCEPTIONS - 1)));
  559. ExceptionList[NumExceptions].s[0] = (TCHAR)'\0';
  560. if (i != 0)
  561. { // then we hit our exceptions limit.
  562. _ftprintf(stderr, TEXT("Too many exceptions listed in source file! "));
  563. _ftprintf(stderr, TEXT("Destination file may be corrupt!\n"));
  564. }
  565. else if (fseek(InputFile, FilePosition, SEEK_SET) != 0) // Restore file pointer
  566. {
  567. _ftprintf(stderr, TEXT("Warning: Cannot seek within INF file! "));
  568. _ftprintf(stderr, TEXT("One line may be lost!\n"));
  569. }
  570. // File pointer now points to the first line that is not an Exception line.
  571. return;
  572. }