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.

1039 lines
28 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /**************************************************************************/
  4. /***** Common Library Component - INF File Handling Routines 1 ***********/
  5. /**************************************************************************/
  6. BOOL APIENTRY FMatchPrefix(PSZ, SZ, BOOL);
  7. GRC APIENTRY GrcHandleSfdOption(INT, POER, UINT);
  8. /*
  9. ** Purpose:
  10. ** Allocates an Object Element Record and initializes it as empty.
  11. ** Arguments:
  12. ** none
  13. ** Returns:
  14. ** NULL if allocation fails.
  15. ** non-NULL pointer to the empty (initialized) Object Element Record.
  16. **
  17. **************************************************************************/
  18. POER APIENTRY PoerAlloc(VOID)
  19. {
  20. POER poer;
  21. AssertDataSeg();
  22. if ((poer = (POER)SAlloc((CB)sizeof(OER))) != (POER)NULL)
  23. {
  24. poer->oef = oefNone;
  25. poer->ctuCopyTime = (CTU)0;
  26. poer->owm = owmAlways;
  27. poer->lSize = 0L;
  28. poer->szRename = (SZ)NULL;
  29. poer->szAppend = (SZ)NULL;
  30. poer->szBackup = (SZ)NULL;
  31. poer->szDescription = (SZ)NULL;
  32. poer->ulVerMS = 0L;
  33. poer->ulVerLS = 0L;
  34. poer->szDate = (SZ)NULL;
  35. poer->szDest = (SZ)NULL; /* REVIEW EBU */
  36. }
  37. return(poer);
  38. }
  39. /*
  40. ** Purpose:
  41. ** Free an Object Element Record and any non-empty string fields.
  42. ** Arguments:
  43. ** poer: non-NULL Object Element Record to be freed.
  44. ** Returns:
  45. ** fFalse if a freeing error occurs.
  46. ** fTrue for success.
  47. **
  48. **************************************************************************/
  49. BOOL APIENTRY FFreePoer(poer)
  50. POER poer;
  51. {
  52. AssertDataSeg();
  53. ChkArg(poer != (POER)NULL, 1, fFalse);
  54. if (poer->szRename != (SZ)NULL)
  55. SFree(poer->szRename);
  56. if (poer->szAppend != (SZ)NULL)
  57. SFree(poer->szAppend);
  58. if (poer->szBackup != (SZ)NULL)
  59. SFree(poer->szBackup);
  60. if (poer->szDescription != (SZ)NULL)
  61. SFree(poer->szDescription);
  62. if (poer->szDate != (SZ)NULL)
  63. SFree(poer->szDate);
  64. if (poer->szDest != (SZ)NULL) /* REVIEW EBU */
  65. SFree(poer->szDest);
  66. SFree(poer);
  67. return(fTrue);
  68. }
  69. /*
  70. ** Purpose:
  71. ** Validates an Option Element Record.
  72. ** Arguments:
  73. ** poer: non-Null pointer to OER to validate.
  74. ** Returns:
  75. ** fFalse if not valid.
  76. ** fTrue if valid.
  77. **
  78. **************************************************************************/
  79. BOOL APIENTRY FValidPoer(poer)
  80. POER poer;
  81. {
  82. AssertDataSeg();
  83. ChkArg(poer != (POER)NULL, 1, fFalse);
  84. if (poer->szBackup != (SZ)NULL &&
  85. poer->szAppend != (SZ)NULL)
  86. return(fFalse);
  87. if (poer->szRename != (SZ)NULL &&
  88. poer->szAppend != (SZ)NULL)
  89. return(fFalse);
  90. if (poer->szRename != (SZ)NULL &&
  91. poer->oef & oefRoot)
  92. return(fFalse);
  93. if (poer->szAppend != (SZ)NULL &&
  94. poer->oef & oefRoot)
  95. return(fFalse);
  96. if (poer->szRename != (SZ)NULL &&
  97. CchlValidSubPath(poer->szRename) == (CCHL)0)
  98. return(fFalse);
  99. if (poer->szAppend != (SZ)NULL &&
  100. CchlValidSubPath(poer->szAppend) == (CCHL)0)
  101. return(fFalse);
  102. if (poer->szBackup != (SZ)NULL &&
  103. (*(poer->szBackup) != '*' ||
  104. *(poer->szBackup + 1) != '\0') &&
  105. CchlValidSubPath(poer->szBackup) == (CCHL)0)
  106. return(fFalse);
  107. if (poer->szDate != (SZ)NULL &&
  108. !FValidOerDate(poer->szDate))
  109. return(fFalse);
  110. if (poer->lSize < 0L)
  111. return(fFalse);
  112. if (poer->owm != owmNever &&
  113. poer->owm != owmAlways &&
  114. poer->owm != owmUnprotected &&
  115. poer->owm != owmOlder &&
  116. poer->owm != owmVerifySourceOlder)
  117. return(fFalse);
  118. /* REVIEW EBU - no checking for szDest field */
  119. return(fTrue);
  120. }
  121. /*
  122. ** Purpose:
  123. ** Allocates a Section File Descriptor and initializes it as empty.
  124. ** Arguments:
  125. ** none
  126. ** Returns:
  127. ** NULL if allocation fails.
  128. ** non-NULL pointer to the empty (initialized) Section File Descriptor.
  129. **
  130. **************************************************************************/
  131. PSFD APIENTRY PsfdAlloc(VOID)
  132. {
  133. PSFD psfd;
  134. AssertDataSeg();
  135. if ((psfd = (PSFD)SAlloc((CB)sizeof(SFD))) != (PSFD)NULL)
  136. {
  137. POER poer = &(psfd->oer);
  138. psfd->did = didMin;
  139. psfd->szFile = (SZ)NULL;
  140. poer->oef = oefNone;
  141. poer->ctuCopyTime = (CTU)0;
  142. poer->owm = owmAlways;
  143. poer->lSize = 0L;
  144. poer->szRename = (SZ)NULL;
  145. poer->szAppend = (SZ)NULL;
  146. poer->szBackup = (SZ)NULL;
  147. poer->szDescription = (SZ)NULL;
  148. poer->ulVerMS = 0L;
  149. poer->ulVerLS = 0L;
  150. poer->szDate = (SZ)NULL;
  151. poer->szDest = (SZ)NULL; /* REVIEW EBU */
  152. }
  153. return(psfd);
  154. }
  155. /*
  156. ** Purpose:
  157. ** Free a Section File Descriptor and any non-empty string fields.
  158. ** Arguments:
  159. ** psfd: non-NULL Section File Descriptor to be freed.
  160. ** Returns:
  161. ** fFalse if a freeing error occurs.
  162. ** fTrue for success.
  163. **
  164. **************************************************************************/
  165. BOOL APIENTRY FFreePsfd(psfd)
  166. PSFD psfd;
  167. {
  168. AssertDataSeg();
  169. ChkArg(psfd != (PSFD)NULL, 1, fFalse);
  170. if (psfd->szFile != (SZ)NULL)
  171. SFree(psfd->szFile);
  172. if ((psfd->oer).szRename != (SZ)NULL)
  173. SFree((psfd->oer).szRename);
  174. if ((psfd->oer).szAppend != (SZ)NULL)
  175. SFree((psfd->oer).szAppend);
  176. if ((psfd->oer).szBackup != (SZ)NULL)
  177. SFree((psfd->oer).szBackup);
  178. if ((psfd->oer).szDescription != (SZ)NULL)
  179. SFree((psfd->oer).szDescription);
  180. if ((psfd->oer).szDate != (SZ)NULL)
  181. SFree((psfd->oer).szDate);
  182. if ((psfd->oer).szDest != (SZ)NULL)
  183. SFree((psfd->oer).szDest);
  184. SFree(psfd);
  185. return(fTrue);
  186. }
  187. #if DBG
  188. /*
  189. ** Purpose:
  190. ** Validates a Section File Descriptor.
  191. ** Arguments:
  192. ** psfd: non-Null pointer to SFD to validate.
  193. ** Returns:
  194. ** fFalse if not valid.
  195. ** fTrue if valid.
  196. **
  197. **************************************************************************/
  198. BOOL APIENTRY FValidPsfd(psfd)
  199. PSFD psfd;
  200. {
  201. AssertDataSeg();
  202. ChkArg(psfd != (PSFD)NULL, 1, fFalse);
  203. if (psfd->did < didMin ||
  204. psfd->did > didMost ||
  205. psfd->szFile == (SZ)NULL ||
  206. CchlValidSubPath(psfd->szFile) == (CCHP)0)
  207. return(fFalse);
  208. return(FValidPoer(&(psfd->oer)));
  209. }
  210. #endif
  211. /*
  212. ** Purpose:
  213. ** Validates a Section File Descriptor Date string of the form
  214. ** "YYYY-MM-DD" where YYYY is >= 1980 and <= 2099, MM in [01..12],
  215. ** and DD in [01..31].
  216. ** Arguments:
  217. ** sz: non-Null Date string to validate.
  218. ** Returns:
  219. ** fFalse if invalid.
  220. ** fTrue if valid.
  221. **
  222. **************************************************************************/
  223. BOOL APIENTRY FValidOerDate(sz)
  224. SZ sz;
  225. {
  226. AssertDataSeg();
  227. ChkArg(sz != (SZ)NULL, 1, fFalse);
  228. if (*sz == '\0' ||
  229. strlen(sz) != (CCHP)10 ||
  230. !isdigit(*(sz + 0)) ||
  231. !isdigit(*(sz + 1)) ||
  232. !isdigit(*(sz + 2)) ||
  233. !isdigit(*(sz + 3)) ||
  234. !isdigit(*(sz + 5)) ||
  235. !isdigit(*(sz + 6)) ||
  236. !isdigit(*(sz + 8)) ||
  237. !isdigit(*(sz + 9)) ||
  238. *(sz + 4) != '-' ||
  239. *(sz + 7) != '-')
  240. return(fFalse);
  241. if (*sz == '0' ||
  242. *sz > '2' ||
  243. (*sz == '1' &&
  244. (*(sz + 1) != '9' ||
  245. *(sz + 2) < '8')) ||
  246. (*sz == '2' &&
  247. *(sz + 1) != '0'))
  248. return(fFalse);
  249. if (*(sz + 5) > '1' ||
  250. (*(sz + 5) == '0' &&
  251. *(sz + 6) == '0') ||
  252. (*(sz + 5) == '1' &&
  253. *(sz + 6) > '2'))
  254. return(fFalse);
  255. if (*(sz + 8) > '3' ||
  256. (*(sz + 8) == '0' &&
  257. *(sz + 9) == '0') ||
  258. (*(sz + 8) == '3' &&
  259. *(sz + 9) > '1'))
  260. return(fFalse);
  261. return(fTrue);
  262. }
  263. /*
  264. ** Purpose:
  265. ** Ensures rest of SFD option string matches (case insensitive compare)
  266. ** and consumes option string through matching portion and a trailing
  267. ** equals sign (if required).
  268. ** Arguments:
  269. ** psz: non-NULL pointer to non-NULL option string to match.
  270. ** szToMatch: non-Null uppercase string to match.
  271. ** fEquals: whether string must be terminated by an equals sign.
  272. ** Returns:
  273. ** fFalse for mismatch or bad format of option.
  274. ** fTrue otherwise.
  275. **
  276. **************************************************************************/
  277. BOOL APIENTRY FMatchPrefix(PSZ psz,SZ szToMatch,BOOL fEquals)
  278. {
  279. AssertDataSeg();
  280. ChkArg(psz != (PSZ)NULL &&
  281. *psz != (SZ)NULL, 1, fFalse);
  282. ChkArg(szToMatch != (SZ)NULL &&
  283. *szToMatch >= 'A' &&
  284. *szToMatch <= 'Z', 2, fFalse);
  285. while (**psz != '\0' &&
  286. **psz != '=' &&
  287. !FWhiteSpaceChp(**psz) &&
  288. *szToMatch != '\0')
  289. {
  290. if (**psz != *szToMatch)
  291. return(fFalse);
  292. (*psz)++;
  293. szToMatch++;
  294. }
  295. if (fEquals)
  296. {
  297. if (**psz != '=')
  298. return(fFalse);
  299. else
  300. (*psz)++;
  301. }
  302. else if (**psz != '\0')
  303. return(fFalse);
  304. return(fTrue);
  305. }
  306. /*
  307. ** Purpose:
  308. ** Parses a string representation of a version into two unsigned
  309. ** long values - the most significant and the least significant.
  310. ** Arguments:
  311. ** szVer: non-Null SZ of the form "a,b,c,d" where each field is
  312. ** an unsigned word. Omitted fields are assumed to be the least
  313. ** significant (eg d then c then b then a) and are parsed as zeros.
  314. ** So "a,b" is equivalent to "a,b,0,0".
  315. ** pulMS: non-Null location to store the Most Significant long value
  316. ** built from a,b
  317. ** pulLS: non-Null location to store the Least Significant long value
  318. ** built from c,d
  319. ** Returns:
  320. ** fFalse if szVer is of a bad format.
  321. ** fTrue otherwise.
  322. **
  323. **************************************************************************/
  324. BOOL APIENTRY FParseVersion(szVer, pulMS, pulLS)
  325. SZ szVer;
  326. PULONG pulMS;
  327. PULONG pulLS;
  328. {
  329. USHORT rgus[4];
  330. USHORT ius;
  331. ULONG ulTmp;
  332. AssertDataSeg();
  333. ChkArg(szVer != (SZ)NULL, 1, fFalse);
  334. ChkArg(pulMS != (PULONG)NULL, 2, fFalse);
  335. ChkArg(pulLS != (PULONG)NULL, 3, fFalse);
  336. *pulMS = *pulLS = 0L;
  337. for (ius = 0; ius < 4; ius++) {
  338. rgus[ius] = (USHORT) atoi(szVer);
  339. while (*szVer != '\0' && *szVer != ',') {
  340. if (!isdigit(*szVer++)) {
  341. return(fFalse);
  342. }
  343. }
  344. if (*szVer == ',') {
  345. szVer++;
  346. }
  347. }
  348. ulTmp = rgus[0];
  349. *pulMS = (ulTmp << 16) + rgus[1];
  350. ulTmp = rgus[2];
  351. *pulLS = (ulTmp << 16) + rgus[3];
  352. return(fTrue);
  353. // // no versioning in WIN32
  354. // Unused(szVer);
  355. // Unused(pulMS);
  356. // Unused(pulLS);
  357. // return(fTrue);
  358. }
  359. /*
  360. ** Purpose:
  361. ** Handles one option field from a file description line.
  362. ** Arguments:
  363. ** poer: non-NULL valid OER to fill.
  364. ** iField: index of existing field to read.
  365. ** Notes:
  366. ** Requires that the current INF structure was initialized with a
  367. ** successful call to GrcOpenInf() and that the current Read location
  368. ** is valid.
  369. ** Returns:
  370. ** grcOkay for success.
  371. ** grcOutOfMemory for out of memory.
  372. ** grcINFBadFDLine for bad format.
  373. ** grcNotOkay otherwise.
  374. **
  375. **************************************************************************/
  376. GRC APIENTRY GrcHandleSfdOption(INT Line,POER poer,UINT iField)
  377. {
  378. SZ sz, szCur;
  379. GRC grc = grcOkay;
  380. BOOL fNot = fFalse;
  381. AssertDataSeg();
  382. PreCondInfOpen(grcNotOkay);
  383. ChkArg(poer != (POER)NULL, 1, grcNotOkay);
  384. ChkArg(FValidPoer(poer), 1, grcNotOkay);
  385. ChkArg(iField >= 1 && CFieldsInInfLine(Line) >= iField, 2, grcNotOkay);
  386. if ((szCur = sz = SzGetNthFieldFromInfLine(Line,iField)) == (SZ)NULL)
  387. return(grcOutOfMemory);
  388. if (*szCur == '!')
  389. {
  390. fNot = fTrue;
  391. szCur++;
  392. }
  393. switch (*szCur)
  394. {
  395. case 'A':
  396. if (!FMatchPrefix(&szCur, "APPEND", !fNot))
  397. grc = grcINFBadFDLine;
  398. else if (fNot)
  399. poer->szAppend = (SZ)NULL;
  400. else if ((poer->szAppend = SzDupl(szCur)) == (SZ)NULL)
  401. grc = grcOutOfMemory;
  402. else if (CchlValidSubPath(poer->szAppend) == (CCHP)0 ||
  403. poer->szBackup != (SZ)NULL ||
  404. poer->szRename != (SZ)NULL ||
  405. (poer->oef & oefRoot) == oefRoot)
  406. grc = grcINFBadFDLine;
  407. break;
  408. case 'B':
  409. if (!FMatchPrefix(&szCur, "BACKUP", !fNot))
  410. grc = grcINFBadFDLine;
  411. else if (fNot)
  412. poer->szBackup = (SZ)NULL;
  413. else if ((poer->szBackup = SzDupl(szCur)) == (SZ)NULL)
  414. grc = grcOutOfMemory;
  415. else if ((*(poer->szBackup) != '*' ||
  416. *(poer->szBackup + 1) != '\0') &&
  417. CchlValidSubPath(poer->szBackup) == (CCHP)0)
  418. grc = grcINFBadFDLine;
  419. else if (poer->szAppend != (SZ)NULL)
  420. grc = grcINFBadFDLine;
  421. break;
  422. case 'C':
  423. if (!FMatchPrefix(&szCur, "COPY", fFalse))
  424. grc = grcINFBadFDLine;
  425. else if (fNot)
  426. poer->oef &= ~oefCopy;
  427. else
  428. poer->oef |= oefCopy;
  429. break;
  430. case 'D': /* Date, Decompress, Description */
  431. if (*(szCur + 1) == 'A')
  432. {
  433. if (!FMatchPrefix(&szCur, "DATE", !fNot))
  434. grc = grcINFBadFDLine;
  435. else if (fNot)
  436. poer->szDate = (SZ)NULL;
  437. else if ((poer->szDate = SzDupl(szCur)) == (SZ)NULL)
  438. grc = grcOutOfMemory;
  439. else if (!FValidOerDate(poer->szDate))
  440. grc = grcINFBadFDLine;
  441. }
  442. else if (*(szCur + 1) == 'E')
  443. {
  444. if (*(szCur + 2) == 'C')
  445. {
  446. if (!FMatchPrefix(&szCur, "DECOMPRESS", fFalse))
  447. grc = grcINFBadFDLine;
  448. else if (fNot)
  449. poer->oef &= ~oefDecompress;
  450. else
  451. poer->oef |= oefDecompress;
  452. }
  453. else if (*(szCur + 2) == 'S')
  454. {
  455. if (*(szCur + 3) == 'C')
  456. {
  457. if (!FMatchPrefix(&szCur, "DESCRIPTION", !fNot))
  458. grc = grcINFBadFDLine;
  459. else if (fNot)
  460. poer->szDescription = (SZ)NULL;
  461. else if ((poer->szDescription = SzDupl(szCur)) == (SZ)NULL)
  462. grc = grcOutOfMemory;
  463. }
  464. else if (*(szCur + 3) == 'T') /* REVIEW EBU */
  465. {
  466. if (!FMatchPrefix(&szCur, "DESTINATION", !fNot))
  467. grc = grcINFBadFDLine;
  468. else if (fNot)
  469. poer->szDest = (SZ)NULL;
  470. else if ((poer->szDest = SzDupl(szCur)) == (SZ)NULL)
  471. grc = grcOutOfMemory;
  472. }
  473. else
  474. grc = grcINFBadFDLine;
  475. }
  476. else
  477. grc = grcINFBadFDLine;
  478. }
  479. else
  480. grc = grcINFBadFDLine;
  481. break;
  482. case 'N': /* NoDeleteSource, NoLog */
  483. if(*(szCur + 1) == 'O') {
  484. if(*(szCur + 2) == 'D') {
  485. if(!FMatchPrefix(&szCur, "NODELETESOURCE", fFalse)) {
  486. grc = grcINFBadFDLine;
  487. } else if (fNot) {
  488. poer->oef &= ~oefNoDeleteSource;
  489. } else {
  490. poer->oef |= oefNoDeleteSource;
  491. }
  492. } else if(*(szCur + 2) == 'L') {
  493. if(!FMatchPrefix(&szCur, "NOLOG", fFalse)) {
  494. grc = grcINFBadFDLine;
  495. } else if (fNot) {
  496. poer->oef &= ~oefNoLog;
  497. } else {
  498. poer->oef |= oefNoLog;
  499. }
  500. }
  501. } else {
  502. grc = grcINFBadFDLine;
  503. }
  504. break;
  505. case 'O':
  506. if (!FMatchPrefix(&szCur, "OVERWRITE", !fNot))
  507. grc = grcINFBadFDLine;
  508. else if (fNot)
  509. poer->owm = owmNever;
  510. else
  511. {
  512. switch (*szCur)
  513. {
  514. case 'A':
  515. if (!FMatchPrefix(&szCur, "ALWAYS", fFalse))
  516. grc = grcINFBadFDLine;
  517. poer->owm = owmAlways;
  518. break;
  519. case 'N':
  520. if (!FMatchPrefix(&szCur, "NEVER", fFalse))
  521. grc = grcINFBadFDLine;
  522. poer->owm = owmNever;
  523. break;
  524. case 'O':
  525. if (!FMatchPrefix(&szCur, "OLDER", fFalse))
  526. grc = grcINFBadFDLine;
  527. poer->owm = owmOlder;
  528. break;
  529. case 'V':
  530. if (!FMatchPrefix(&szCur, "VERIFYSOURCEOLDER", fFalse))
  531. grc = grcINFBadFDLine;
  532. poer->owm = owmVerifySourceOlder;
  533. break;
  534. case 'U':
  535. if (!FMatchPrefix(&szCur, "UNPROTECTED", fFalse))
  536. grc = grcINFBadFDLine;
  537. poer->owm = owmUnprotected;
  538. break;
  539. default:
  540. grc = grcINFBadFDLine;
  541. }
  542. }
  543. break;
  544. case 'R': /* ReadOnly, Rename, Root */
  545. if (*(szCur + 1) == 'E')
  546. {
  547. if (*(szCur + 2) == 'A')
  548. {
  549. if (!FMatchPrefix(&szCur, "READONLY", fFalse))
  550. grc = grcINFBadFDLine;
  551. else if (fNot)
  552. poer->oef &= ~oefReadOnly;
  553. else
  554. poer->oef |= oefReadOnly;
  555. }
  556. else if (*(szCur + 2) == 'N')
  557. {
  558. if (!FMatchPrefix(&szCur, "RENAME", !fNot))
  559. grc = grcINFBadFDLine;
  560. else if (fNot)
  561. poer->szRename = (SZ)NULL;
  562. else if ((poer->szRename = SzDupl(szCur)) == (SZ)NULL)
  563. grc = grcOutOfMemory;
  564. else if (CchlValidSubPath(poer->szRename) == (CCHP)0 ||
  565. poer->szAppend != (SZ)NULL ||
  566. (poer->oef & oefRoot) == oefRoot)
  567. grc = grcINFBadFDLine;
  568. }
  569. else
  570. grc = grcINFBadFDLine;
  571. }
  572. else if (*(szCur + 1) == 'O')
  573. {
  574. if (!FMatchPrefix(&szCur, "ROOT", fFalse))
  575. grc = grcINFBadFDLine;
  576. else if (fNot)
  577. poer->oef &= ~oefRoot;
  578. else if (poer->szAppend != (SZ)NULL ||
  579. poer->szRename != (SZ)NULL)
  580. grc = grcINFBadFDLine;
  581. else
  582. poer->oef |= oefRoot;
  583. }
  584. else
  585. grc = grcINFBadFDLine;
  586. break;
  587. case 'S': /* SetTimeStamp, Size */
  588. if (*(szCur + 1) == 'E')
  589. {
  590. if (!FMatchPrefix(&szCur, "SETTIMESTAMP", fFalse))
  591. grc = grcINFBadFDLine;
  592. else if (fNot)
  593. poer->oef &= ~oefTimeStamp;
  594. else
  595. poer->oef |= oefTimeStamp;
  596. }
  597. else if (*(szCur + 1) == 'I')
  598. {
  599. if (!FMatchPrefix(&szCur, "SIZE", !fNot))
  600. grc = grcINFBadFDLine;
  601. else if (fNot)
  602. poer->lSize = 0L;
  603. else if ((poer->lSize = ((LONG)atol(szCur) / 100 )) < 0L)
  604. grc = grcINFBadFDLine;
  605. else
  606. poer->lSize = poer->lSize + 1; // make size atleast one
  607. }
  608. else
  609. grc = grcINFBadFDLine;
  610. break;
  611. case 'T':
  612. if (!FMatchPrefix(&szCur, "TIME", !fNot))
  613. grc = grcINFBadFDLine;
  614. else if (fNot)
  615. poer->ctuCopyTime = (CTU)0;
  616. else
  617. {
  618. LONG l = (LONG)atol(szCur);
  619. if (l < 0L)
  620. grc = grcINFBadFDLine;
  621. else
  622. poer->ctuCopyTime = (CTU)l;
  623. }
  624. break;
  625. case 'U':
  626. if (FMatchPrefix(&szCur, "UNDO", fFalse)) {
  627. if (fNot) {
  628. poer->oef &= ~oefUndo;
  629. }
  630. else {
  631. poer->oef |= oefUndo;
  632. }
  633. }
  634. else if (FMatchPrefix(&szCur, "UPGRADEONLY", fFalse)) {
  635. if (fNot) {
  636. poer->oef &= ~oefUpgradeOnly;
  637. }
  638. else {
  639. poer->oef |= oefUpgradeOnly;
  640. }
  641. }
  642. else {
  643. grc = grcINFBadFDLine;
  644. }
  645. break;
  646. case 'V': /* Version, Vital */
  647. if (*(szCur + 1) == 'E')
  648. {
  649. if (!FMatchPrefix(&szCur, "VERSION", !fNot))
  650. grc = grcINFBadFDLine;
  651. else if (fNot)
  652. {
  653. poer->ulVerMS = 0L;
  654. poer->ulVerLS = 0L;
  655. }
  656. else if (!FParseVersion(szCur, &(poer->ulVerMS), &(poer->ulVerLS)))
  657. grc = grcINFBadFDLine;
  658. }
  659. else if (*(szCur + 1) == 'I')
  660. {
  661. if (!FMatchPrefix(&szCur, "VITAL", fFalse))
  662. grc = grcINFBadFDLine;
  663. else if (fNot)
  664. poer->oef &= ~oefVital;
  665. else
  666. poer->oef |= oefVital;
  667. }
  668. else
  669. grc = grcINFBadFDLine;
  670. break;
  671. default:
  672. grc = grcINFBadFDLine;
  673. }
  674. SFree(sz);
  675. Assert(grc != grcOkay || FValidPoer(poer));
  676. return(grc);
  677. }
  678. /*
  679. ** Purpose:
  680. ** Allocates a new Section File Descriptor and fills it by reading and
  681. ** parsing the given INF read line.
  682. ** Arguments:
  683. ** ppsfd: non-Null location to store PSFD if successful.
  684. ** poer: non-Null valid filled OER pointer.
  685. ** Notes:
  686. ** Requires that the current INF structure was initialized with a
  687. ** successful call to GrcOpenInf().
  688. ** Returns:
  689. ** grcOkay if successful.
  690. ** grcOutOfMemory if out of memory.
  691. ** grcINFBadFDLine if the current line has a bad format.
  692. ** grcNotOkay otherwise.
  693. **
  694. **************************************************************************/
  695. GRC APIENTRY GrcGetSectionFileLine(INT Line,PPSFD ppsfd,POER poer)
  696. {
  697. PSFD psfd;
  698. UINT cFields, iField;
  699. SZ sz;
  700. AssertDataSeg();
  701. PreCondInfOpen(grcNotOkay);
  702. ChkArg(ppsfd != (PPSFD)NULL, 1, grcNotOkay);
  703. ChkArg(poer != (POER)NULL, 2, grcNotOkay);
  704. ChkArg(FValidPoer(poer), 2, grcNotOkay);
  705. *ppsfd = (PSFD)NULL;
  706. if ((cFields = CFieldsInInfLine(Line)) < 2)
  707. return(grcINFBadFDLine);
  708. if ((psfd = PsfdAlloc()) == (PSFD)NULL)
  709. return(grcOutOfMemory);
  710. if ((sz = SzGetNthFieldFromInfLine(Line,1)) == (SZ)NULL)
  711. {
  712. EvalAssert(FFreePsfd(psfd));
  713. return(grcOutOfMemory);
  714. }
  715. if ((psfd->did = (DID)atoi(sz)) < didMin ||
  716. psfd->did > didMost)
  717. {
  718. SFree(sz);
  719. EvalAssert(FFreePsfd(psfd));
  720. return(grcINFBadFDLine);
  721. }
  722. psfd->InfId = pLocalInfPermInfo()->InfId;
  723. SFree(sz);
  724. if ((psfd->szFile = SzGetNthFieldFromInfLine(Line,2)) == (SZ)NULL)
  725. {
  726. EvalAssert(FFreePsfd(psfd));
  727. return(grcOutOfMemory);
  728. }
  729. if (CchlValidSubPath(psfd->szFile) == (CCHP)0)
  730. {
  731. EvalAssert(FFreePsfd(psfd));
  732. return(grcINFBadFDLine);
  733. }
  734. psfd->oer = *poer;
  735. for (iField = 3; iField <= cFields; iField++)
  736. {
  737. GRC grc;
  738. if ((grc = GrcHandleSfdOption(Line, &(psfd->oer), iField)) != grcOkay)
  739. {
  740. /* REVIEW - could just reset all and leave a few strings! */
  741. if ((psfd->oer).szAppend == poer->szAppend)
  742. (psfd->oer).szAppend = (SZ)NULL;
  743. if ((psfd->oer).szBackup == poer->szBackup)
  744. (psfd->oer).szBackup = (SZ)NULL;
  745. if ((psfd->oer).szDate == poer->szDate)
  746. (psfd->oer).szDate = (SZ)NULL;
  747. if ((psfd->oer).szDescription == poer->szDescription)
  748. (psfd->oer).szDescription = (SZ)NULL;
  749. if ((psfd->oer).szDest == poer->szDest) /* REVIEW EBU */
  750. (psfd->oer).szDest = (SZ)NULL;
  751. if ((psfd->oer).szRename == poer->szRename)
  752. (psfd->oer).szRename = (SZ)NULL;
  753. EvalAssert(FFreePsfd(psfd));
  754. return(grc);
  755. }
  756. }
  757. AssertRet(FValidPsfd(psfd), grcNotOkay);
  758. *ppsfd = psfd;
  759. return(grcOkay);
  760. }
  761. /*
  762. ** Purpose:
  763. ** Determines if the given INF line is a list-include statement of
  764. ** the form: [ <Key> = ] @( <Section> ) [, @( <Key> ) ]
  765. ** Arguments:
  766. ** none
  767. ** Notes:
  768. ** Requires that the current INF structure was initialized with a
  769. ** successful call to GrcOpenInf() and that the current Read location
  770. ** is valid.
  771. ** Returns:
  772. ** fTrue if current INF line conforms to above format.
  773. ** fFalse if it does not.
  774. **
  775. **************************************************************************/
  776. BOOL APIENTRY FListIncludeStatementLine(INT Line)
  777. {
  778. UINT cFields;
  779. SZ sz, szLast;
  780. AssertDataSeg();
  781. PreCondInfOpen(fFalse);
  782. if ((cFields = CFieldsInInfLine(Line)) < 1 ||
  783. cFields > 2 ||
  784. (sz = SzGetNthFieldFromInfLine(Line,1)) == (SZ)NULL)
  785. return(fFalse);
  786. if (*sz != '@' ||
  787. *(sz + 1) != '(' ||
  788. (szLast = SzLastChar(sz)) == (SZ)NULL ||
  789. *szLast != ')')
  790. goto L_FLISL_ERROR;
  791. SFree(sz);
  792. if (cFields == 1)
  793. return(fTrue);
  794. if ((sz = SzGetNthFieldFromInfLine(Line,2)) == (SZ)NULL)
  795. return(fFalse);
  796. if (*sz != '@' ||
  797. *(sz + 1) != '(' ||
  798. (szLast = SzLastChar(sz)) == (SZ)NULL ||
  799. *szLast != ')')
  800. goto L_FLISL_ERROR;
  801. SFree(sz);
  802. return(fTrue);
  803. L_FLISL_ERROR:
  804. if (sz != (SZ)NULL)
  805. SFree(sz);
  806. return(fFalse);
  807. }
  808. /*
  809. ** Purpose:
  810. ** Parses a list-include-statement from an INF file description section.
  811. ** Arguments:
  812. ** pszSection: non-Null pointer to a currently Null string which this
  813. ** routine will replace with a pointer to an allocated buffer
  814. ** containing the section name on the line.
  815. ** pszKey: non-Null pointer to a currently Null string which this
  816. ** routine will replace with a pointer to an allocated buffer
  817. ** containing the key name on the line if one exists.
  818. ** Notes:
  819. ** Requires that the current INF structure was initialized with a
  820. ** successful call to GrcOpenInf() and that the current Read location
  821. ** is valid and that it points to a valid list-include statement.
  822. ** Returns:
  823. ** grcOkay if successful.
  824. ** grcOutOfMemory if out of memory.
  825. ** grcNotOkay otherwise.
  826. **
  827. **************************************************************************/
  828. GRC APIENTRY GrcGetListIncludeSectionLine(INT Line,
  829. PSZ pszSection,
  830. PSZ pszKey)
  831. {
  832. UINT cFields;
  833. SZ sz, szLast;
  834. AssertDataSeg();
  835. PreCondInfOpen(grcNotOkay);
  836. PreCondition(FListIncludeStatementLine(Line), grcNotOkay);
  837. ChkArg(pszSection != (PSZ)NULL && *pszSection == (SZ)NULL, 1, grcNotOkay);
  838. ChkArg(pszKey != (PSZ)NULL && *pszKey == (SZ)NULL, 2, grcNotOkay);
  839. EvalAssert((cFields = CFieldsInInfLine(Line)) == 1 || cFields == 2);
  840. if ((sz = SzGetNthFieldFromInfLine(Line,1)) == (SZ)NULL)
  841. return(grcOutOfMemory);
  842. Assert(*sz == '@' && *(sz + 1) == '(');
  843. EvalAssert((szLast = SzLastChar(sz)) != (SZ)NULL);
  844. Assert(*szLast == ')');
  845. *szLast = '\0';
  846. *pszSection = SzDupl(sz + 2);
  847. *szLast = ')';
  848. if (*pszSection == (SZ)NULL)
  849. goto L_GGLISL_ERROR;
  850. SFree(sz);
  851. sz = (SZ)NULL;
  852. if (cFields == 1)
  853. return(grcOkay);
  854. Assert(cFields == 2);
  855. if ((sz = SzGetNthFieldFromInfLine(Line,2)) == (SZ)NULL)
  856. goto L_GGLISL_ERROR;
  857. Assert(*sz == '@' && *(sz + 1) == '(');
  858. EvalAssert((szLast = SzLastChar(sz)) != (SZ)NULL);
  859. Assert(*szLast == ')');
  860. *szLast = '\0';
  861. *pszKey = SzDupl(sz + 2);
  862. *szLast = ')';
  863. if (*pszKey == (SZ)NULL)
  864. goto L_GGLISL_ERROR;
  865. SFree(sz);
  866. return(grcOkay);
  867. L_GGLISL_ERROR:
  868. if (sz != (SZ)NULL)
  869. SFree(sz);
  870. if (*pszSection != (SZ)NULL)
  871. SFree(*pszSection);
  872. if (*pszKey != (SZ)NULL)
  873. SFree(*pszKey);
  874. return(grcOutOfMemory);
  875. }