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.

1388 lines
31 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. infparse.c
  5. Abstract:
  6. The code in this file read in an INF file, organizing it into a data
  7. structure that can be maniuplated along with an STF file. The INF
  8. data structure is stored along with the STF table data strcture.
  9. This INF parser does not preserve comments. It is designed specifically
  10. for the STF migration code.
  11. The entry points are:
  12. InfParse_ReadInfIntoTable - Parses the INF associated with the STF file.
  13. InfParse_WriteInfToDisk - Writes the INF memory structure to disk
  14. AddInfSectionToTable - Adds a new section to the INF memory structure
  15. AddInfLineToTable - Adds a new line to a section's memory structure
  16. FindInfSectionInTable - Performs a sequential search for a specific
  17. section name
  18. FindLineInInfSection - Locates a line given a specific key
  19. DeleteLineInInfSection - Removes a line from an INF section
  20. DeleteSectionInInfFile - Removes a complete section from the INF memory
  21. structure
  22. GetInfSectionLineCount - Returns the number of lines in a section
  23. GetFirstLineInSectionStruct - Begins a line enumeration given an INF
  24. section ptr
  25. GetFirstLineInSectionStr - Begins a line enumeration given an INF
  26. section string
  27. GetNextLineInSection - Continues a line enumeration
  28. Author:
  29. Jim Schmidt (jimschm) 20-Sept-1997
  30. Revision History:
  31. --*/
  32. #include "pch.h"
  33. #include "migmainp.h"
  34. #include "stftable.h"
  35. //
  36. // Globals to manage INF file reading
  37. //
  38. static PBYTE g_Buf1, g_Buf2;
  39. static DWORD g_Buf1Start, g_Buf2Start;
  40. static DWORD g_Buf1End, g_Buf2End;
  41. #define INF_BUFFER_SIZE 32768
  42. WCHAR
  43. pStfGetInfFileWchar (
  44. IN HANDLE File,
  45. IN DWORD Pos,
  46. OUT PBOOL Error
  47. );
  48. PCTSTR
  49. pStfGetNextInfLine (
  50. IN HANDLE File,
  51. IN PGROWBUFFER LineBuf,
  52. IN OUT PDWORD Pos,
  53. IN BOOL UnicodeMode
  54. );
  55. BOOL
  56. InfParse_ReadInfIntoTable (
  57. IN OUT PSETUPTABLE TablePtr
  58. )
  59. /*++
  60. Routine Description:
  61. Reads the specified file into memory, parsing the lines according to basic
  62. INF structure. This routine requires an initalized SETUPTABLE structure.
  63. (See CreateSetupTable in stftable.c.)
  64. The INF is assumed to be in the ANSI DBCS character set.
  65. Arguments:
  66. TablePtr - Specifies the STF table structure that provides the state for
  67. the STF/INF pair. Receives the complete INF structure.
  68. Return Value:
  69. TRUE if parsing was successful, or FALSE if parsing failed.
  70. --*/
  71. {
  72. WCHAR ch;
  73. BOOL Error;
  74. GROWBUFFER LineBuf = GROWBUF_INIT;
  75. PCTSTR Text;
  76. DWORD Pos;
  77. PCTSTR Key, Data;
  78. PTSTR p, q;
  79. INT i;
  80. PSTFINFSECTION Section = NULL;
  81. DWORD LineFlags;
  82. BOOL Result = FALSE;
  83. Section = StfAddInfSectionToTable (TablePtr, S_EMPTY);
  84. if (!Section) {
  85. LOG ((LOG_ERROR, "Read Inf Into Table: Could not add comment section"));
  86. return FALSE;
  87. }
  88. g_Buf1Start = 0;
  89. g_Buf2Start = 0;
  90. g_Buf1End = 0;
  91. g_Buf2End = 0;
  92. g_Buf1 = (PBYTE) MemAlloc (g_hHeap, 0, INF_BUFFER_SIZE);
  93. g_Buf2 = (PBYTE) MemAlloc (g_hHeap, 0, INF_BUFFER_SIZE);
  94. __try {
  95. //
  96. // Determine if this file is UNICODE
  97. //
  98. ch = pStfGetInfFileWchar (TablePtr->SourceInfFile, 0, &Error);
  99. TablePtr->InfIsUnicode = (ch == 0xfeff) && !Error;
  100. //
  101. // Parse each line.
  102. //
  103. Pos = 0;
  104. while (TRUE) {
  105. //
  106. // Get the line
  107. //
  108. Text = pStfGetNextInfLine (
  109. TablePtr->SourceInfFile,
  110. &LineBuf,
  111. &Pos,
  112. TablePtr->InfIsUnicode
  113. );
  114. if (!Text) {
  115. break;
  116. }
  117. //
  118. // If a comment line or blank line, skip it
  119. //
  120. p = (PTSTR) SkipSpace (Text);
  121. if (!p[0] || _tcsnextc (p) == TEXT(';')) {
  122. if (!StfAddInfLineToTable (TablePtr, Section, NULL, Text, LINEFLAG_ALL_COMMENTS)) {
  123. LOG ((LOG_ERROR, "Read Inf Into Table: Can't add line comments to table", Text));
  124. __leave;
  125. }
  126. continue;
  127. }
  128. //
  129. // If a section line, start the new section
  130. //
  131. if (_tcsnextc (p) == TEXT('[')) {
  132. p = _tcsinc (p);
  133. q = _tcschr (p, TEXT(']'));
  134. if (!q) {
  135. q = GetEndOfString (p);
  136. } else {
  137. *q = 0;
  138. }
  139. Section = StfAddInfSectionToTable (TablePtr, p);
  140. if (!Section) {
  141. LOG ((LOG_ERROR, "Read Inf Into Table: Could not add section %s", p));
  142. __leave;
  143. }
  144. }
  145. //
  146. // Otherwise it must be a valid line
  147. //
  148. else {
  149. if (!Section) {
  150. DEBUGMSG ((DBG_WARNING, "InfParse_ReadInfIntoTable: Ignoring unrecognized line %s", p));
  151. continue;
  152. }
  153. //
  154. // Split key and line: Skip key that is surrounded by quotes, then
  155. // find the first
  156. //
  157. LineFlags = 0;
  158. q = p;
  159. Key = NULL;
  160. Data = Text;
  161. while (_tcsnextc (q) == TEXT('\"')) {
  162. q = _tcschr (_tcsinc (q), TEXT('\"'));
  163. if (!q) {
  164. q = p;
  165. break;
  166. } else {
  167. q = _tcsinc (q);
  168. }
  169. }
  170. i = _tcscspn (q, TEXT("\"="));
  171. if (_tcsnextc (q + i) == TEXT('=')) {
  172. q += i;
  173. Data = SkipSpace (_tcsinc (q));
  174. *q = 0;
  175. q = (PTSTR) SkipSpaceR (Text, q);
  176. if (q && *q) {
  177. q = _tcsinc (q);
  178. *q = 0;
  179. }
  180. Key = p;
  181. if (_tcsnextc (Key) == TEXT('\"')) {
  182. LineFlags |= LINEFLAG_KEY_QUOTED;
  183. Key = _tcsinc (Key);
  184. p = GetEndOfString (Key);
  185. p = (PTSTR) SkipSpaceR (Key, p);
  186. if (p && *p) {
  187. if (_tcsnextc (p) != TEXT('\"')) {
  188. p = _tcsinc (p);
  189. }
  190. *p = 0;
  191. }
  192. }
  193. }
  194. if (!StfAddInfLineToTable (TablePtr, Section, Key, Data, LineFlags)) {
  195. LOG ((LOG_ERROR, "Read Inf Into Table: Can't add line %s to table", Text));
  196. __leave;
  197. }
  198. }
  199. }
  200. if (Pos != GetFileSize (TablePtr->SourceInfFile, NULL)) {
  201. LOG ((LOG_ERROR, "Read Inf Into Table: Could not read entire INF"));
  202. __leave;
  203. }
  204. Result = TRUE;
  205. }
  206. __finally {
  207. MemFree (g_hHeap, 0, g_Buf1);
  208. MemFree (g_hHeap, 0, g_Buf2);
  209. FreeGrowBuffer (&LineBuf);
  210. }
  211. return Result;
  212. }
  213. BOOL
  214. InfParse_WriteInfToDisk (
  215. IN PSETUPTABLE TablePtr
  216. )
  217. /*++
  218. Routine Description:
  219. InfParse_WriteInfToDisk writes the INF represented by the given setup
  220. table to disk. This is done by enumerating the INF data structures in
  221. the setup table. The file name comes from the setup table struct and
  222. was created in CreateSetupTable in stftable.c.
  223. Arguments:
  224. TablePtr - Specifies the table to process
  225. Return Value:
  226. TRUE if successful, FALSE if not.
  227. --*/
  228. {
  229. PSTFINFSECTION Section;
  230. PSTFINFLINE Line;
  231. MYASSERT (TablePtr->SourceInfFile != INVALID_HANDLE_VALUE);
  232. MYASSERT (TablePtr->DestInfFile != INVALID_HANDLE_VALUE);
  233. //
  234. // Write the INF as we have it in memory
  235. //
  236. if (!WriteFileStringA (TablePtr->DestInfFile, "\r\n")) {
  237. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write new line to INF"));
  238. return FALSE;
  239. }
  240. Section = TablePtr->FirstInfSection;
  241. while (Section) {
  242. if (Section->Name[0]) {
  243. if (!WriteFileStringA (TablePtr->DestInfFile, "[") ||
  244. !WriteFileString (TablePtr->DestInfFile, Section->Name) ||
  245. !WriteFileStringA (TablePtr->DestInfFile, "]\r\n")
  246. ) {
  247. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write section name to INF"));
  248. return FALSE;
  249. }
  250. }
  251. Line = Section->FirstLine;
  252. while (Line) {
  253. if (Line->Key) {
  254. if (Line->LineFlags & LINEFLAG_KEY_QUOTED) {
  255. if (!WriteFileStringA (TablePtr->DestInfFile, "\"")) {
  256. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write start key quotes to INF"));
  257. return FALSE;
  258. }
  259. }
  260. if (!WriteFileString (TablePtr->DestInfFile, Line->Key)) {
  261. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write key to INF"));
  262. return FALSE;
  263. }
  264. if (Line->LineFlags & LINEFLAG_KEY_QUOTED) {
  265. if (!WriteFileStringA (TablePtr->DestInfFile, "\"")) {
  266. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write end key quotes to INF"));
  267. return FALSE;
  268. }
  269. }
  270. if (!WriteFileStringA (TablePtr->DestInfFile, " = ")) {
  271. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write equals to INF"));
  272. return FALSE;
  273. }
  274. }
  275. if (!WriteFileString (TablePtr->DestInfFile, Line->Data) ||
  276. !WriteFileStringA (TablePtr->DestInfFile, "\r\n")
  277. ) {
  278. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write key data to INF"));
  279. return FALSE;
  280. }
  281. Line = Line->Next;
  282. }
  283. if (!WriteFileStringA (TablePtr->DestInfFile, "\r\n")) {
  284. LOG ((LOG_ERROR, "Write Inf To Disk: Cannot write end of section line to INF"));
  285. return FALSE;
  286. }
  287. Section = Section->Next;
  288. }
  289. return TRUE;
  290. }
  291. PSTFINFSECTION
  292. StfAddInfSectionToTable (
  293. IN PSETUPTABLE TablePtr,
  294. IN PCTSTR SectionName
  295. )
  296. /*++
  297. Routine Description:
  298. Creates a new section in our linked list structure if necessary.
  299. The return structure can be used to add lines to the section.
  300. Arguments:
  301. TablePtr - Specifies the table to add the INF section to
  302. SectionName - Specifies the name of the new section
  303. Return Value:
  304. A pointer to the new INF section struct, or NULL if an
  305. error occurred.
  306. --*/
  307. {
  308. PSTFINFSECTION NewSection;
  309. //
  310. // Return early if this section already exists
  311. //
  312. NewSection = StfFindInfSectionInTable (TablePtr, SectionName);
  313. if (NewSection) {
  314. return NewSection;
  315. }
  316. //
  317. // Allocate a section struct
  318. //
  319. NewSection = (PSTFINFSECTION) PoolMemGetAlignedMemory (
  320. TablePtr->InfPool,
  321. sizeof (INFSECTION)
  322. );
  323. if (!NewSection) {
  324. return NULL;
  325. }
  326. //
  327. // Fill in members of the struct and link
  328. //
  329. ZeroMemory (NewSection, sizeof (INFSECTION));
  330. NewSection->Name = PoolMemDuplicateString (
  331. TablePtr->InfPool,
  332. SectionName
  333. );
  334. if (!NewSection->Name) {
  335. return NULL;
  336. }
  337. NewSection->Prev = TablePtr->LastInfSection;
  338. if (NewSection->Prev) {
  339. NewSection->Prev->Next = NewSection;
  340. } else {
  341. TablePtr->FirstInfSection = NewSection;
  342. }
  343. TablePtr->LastInfSection = NewSection;
  344. return NewSection;
  345. }
  346. PSTFINFLINE
  347. StfAddInfLineToTable (
  348. IN PSETUPTABLE TablePtr,
  349. IN PSTFINFSECTION SectionPtr,
  350. IN PCTSTR Key, OPTIONAL
  351. IN PCTSTR Data,
  352. IN DWORD LineFlags
  353. )
  354. /*++
  355. Routine Description:
  356. Adds a line to the specified section. The caller specifies the
  357. full formatted data, and an optional key. The caller does NOT
  358. supply the equals sign between the key and data.
  359. Arguments:
  360. TablePtr - Specifies the table to add the INF line to
  361. SectionName - Specifies the name of the section to add the line to
  362. Key - If specified, supplies the left-hand side of the equals line
  363. Data - Specifies the text for the line, or the right-hand side of
  364. the key = value expression.
  365. LineFlags - Specifies the flags for the INF line (see LINEFLAG_*)
  366. Return Value:
  367. TRUE if the line was added to the structure, or FALSE if not.
  368. --*/
  369. {
  370. PSTFINFLINE NewLine;
  371. //
  372. // Allocate line struct
  373. //
  374. NewLine = (PSTFINFLINE) PoolMemGetAlignedMemory (
  375. TablePtr->InfPool,
  376. sizeof (INFLINE)
  377. );
  378. if (!NewLine) {
  379. return NULL;
  380. }
  381. //
  382. // Fill in members of the struct and link
  383. //
  384. ZeroMemory (NewLine, sizeof (INFLINE));
  385. if (Key) {
  386. NewLine->Key = PoolMemDuplicateString (
  387. TablePtr->InfPool,
  388. Key
  389. );
  390. if (!NewLine->Key) {
  391. return NULL;
  392. }
  393. }
  394. NewLine->Data = PoolMemDuplicateString (
  395. TablePtr->InfPool,
  396. Data
  397. );
  398. if (!NewLine->Data) {
  399. return NULL;
  400. }
  401. NewLine->Next = NULL;
  402. NewLine->Prev = SectionPtr->LastLine;
  403. NewLine->Section = SectionPtr;
  404. NewLine->LineFlags = LineFlags;
  405. if (NewLine->Prev) {
  406. NewLine->Prev->Next = NewLine;
  407. } else {
  408. SectionPtr->FirstLine = NewLine;
  409. }
  410. SectionPtr->LastLine = NewLine;
  411. SectionPtr->LineCount++;
  412. return NewLine;
  413. }
  414. PSTFINFSECTION
  415. StfFindInfSectionInTable (
  416. IN PSETUPTABLE TablePtr,
  417. IN PCTSTR SectionName
  418. )
  419. /*++
  420. Routine Description:
  421. Scans the INF for a specific section. This routine scans
  422. the INF structures sequentially and does a case-insensitive
  423. comparison.
  424. Arguments:
  425. TablePtr - Specifies the table to search
  426. SectionName - Specifies the name of the section to find
  427. Return Value:
  428. A pointer to the matching INF section struct, or NULL if
  429. the section was not found.
  430. --*/
  431. {
  432. PSTFINFSECTION Section;
  433. Section = TablePtr->FirstInfSection;
  434. while (Section) {
  435. if (StringIMatch (Section->Name, SectionName)) {
  436. return Section;
  437. }
  438. Section = Section->Next;
  439. }
  440. return NULL;
  441. }
  442. PSTFINFLINE
  443. StfFindLineInInfSection (
  444. IN PSETUPTABLE TablePtr,
  445. IN PSTFINFSECTION Section,
  446. IN PCTSTR Key
  447. )
  448. /*++
  449. Routine Description:
  450. Scans the specified INF section for a specific key. This routine
  451. scans the INF line structures sequentially and does a case-insensitive
  452. comparison.
  453. Arguments:
  454. TablePtr - Specifies the table to search
  455. Section - Specifies the section to search
  456. Key - Specifies the key to find
  457. Return Value:
  458. A pointer to the matching INF line struct, or NULL if
  459. the section was not found.
  460. --*/
  461. {
  462. PSTFINFLINE Line;
  463. Line = Section->FirstLine;
  464. while (Line) {
  465. if (Line->Key && StringIMatch (Line->Key, Key)) {
  466. return Line;
  467. }
  468. Line = Line->Next;
  469. }
  470. return NULL;
  471. }
  472. PSTFINFLINE
  473. StfGetFirstLineInSectionStruct (
  474. IN PSTFINFSECTION Section
  475. )
  476. /*++
  477. Routine Description:
  478. GetFirstLineInSectionStruct returns the first INFLINE pointer for the
  479. section, or NULL if no lines exist. Call GetNextLineInSection to
  480. continue enumeration.
  481. This routine does not return lines consisting only of comments.
  482. Arguments:
  483. Section - Specifies the section structure to enumerate lines frmo
  484. Return Value:
  485. A pointer to the first INFLINE struct, or NULL if no lines exist.
  486. --*/
  487. {
  488. if (!Section->FirstLine) {
  489. return NULL;
  490. }
  491. if (Section->FirstLine->LineFlags & LINEFLAG_ALL_COMMENTS) {
  492. return StfGetNextLineInSection (Section->FirstLine);
  493. }
  494. return Section->FirstLine;
  495. }
  496. PSTFINFLINE
  497. StfGetNextLineInSection (
  498. IN PSTFINFLINE PrevLine
  499. )
  500. /*++
  501. Routine Description:
  502. GetNextLineInSection returns the next INFLINE pointer for the
  503. section, based on the previous line, or NULL if no lines exist.
  504. This routine does not return lines with comments.
  505. Arguments:
  506. PrevLine - Specifies previous line (returned from
  507. GetFirstLineInSectionStruct or GetFirstLineInSectionStr).
  508. Return Value:
  509. This routine does not return lines consisting only of comments.
  510. --*/
  511. {
  512. while (PrevLine) {
  513. PrevLine = PrevLine->Next;
  514. if (!PrevLine || !(PrevLine->LineFlags & LINEFLAG_ALL_COMMENTS)) {
  515. break;
  516. }
  517. }
  518. return PrevLine;
  519. }
  520. PSTFINFLINE
  521. StfGetFirstLineInSectionStr (
  522. IN PSETUPTABLE Table,
  523. IN PCTSTR Section
  524. )
  525. /*++
  526. Routine Description:
  527. GetFirstLineInSectionStruct returns the first INFLINE pointer for the
  528. section, or NULL if no lines exist. Call GetNextLineInSection to
  529. continue enumeration.
  530. Arguments:
  531. Table - Specifies the setup table containing the parsed INF
  532. Section - Specifies the name of the section in the INF
  533. Return Value:
  534. A pointer to the first INFLINE struct, or NULL if no lines exist.
  535. --*/
  536. {
  537. PSTFINFSECTION SectionPtr;
  538. SectionPtr = StfFindInfSectionInTable (Table, Section);
  539. if (!SectionPtr) {
  540. return NULL;
  541. }
  542. return StfGetFirstLineInSectionStruct (SectionPtr);
  543. }
  544. INT
  545. pStfGetInfFileByte (
  546. IN HANDLE File,
  547. IN DWORD Pos
  548. )
  549. /*++
  550. Routine Description:
  551. Returns the byte at the specified position, or -1 if the file could
  552. not be read at that position.
  553. Two buffers are used to allow fast relative access. Memory-mapped
  554. files were NOT used because problems were introduced when the
  555. swap file started filling up during GUI mode.
  556. Arguments:
  557. File - Specifies the file to read
  558. Pos - Specifies the 32-bit file offset to read (zero-based, in bytes)
  559. Return Value:
  560. The byte at the specified position, or -1 if an error was encountered.
  561. (Errors are usually caused by reading past the end of the file.)
  562. --*/
  563. {
  564. DWORD Read;
  565. PBYTE BufSwap;
  566. //
  567. // If we read the buffer previously, then return data in our buffer
  568. //
  569. if (Pos >= g_Buf1Start && Pos < g_Buf1End) {
  570. return g_Buf1[Pos - g_Buf1Start];
  571. }
  572. if (Pos >= g_Buf2Start && Pos < g_Buf2End) {
  573. return g_Buf2[Pos - g_Buf2Start];
  574. }
  575. //
  576. // Buffer not available; move buffer 2 to buffer 1, then read buffer 2
  577. //
  578. g_Buf1Start = g_Buf2Start;
  579. g_Buf1End = g_Buf2End;
  580. BufSwap = g_Buf1;
  581. g_Buf1 = g_Buf2;
  582. g_Buf2 = BufSwap;
  583. g_Buf2Start = Pos - (Pos % 256);
  584. SetFilePointer (File, g_Buf2Start, NULL, FILE_BEGIN);
  585. if (!ReadFile (File, g_Buf2, INF_BUFFER_SIZE, &Read, NULL)) {
  586. return -1;
  587. }
  588. g_Buf2End = g_Buf2Start + Read;
  589. if (Pos >= g_Buf2Start && Pos < g_Buf2End) {
  590. return g_Buf2[Pos - g_Buf2Start];
  591. }
  592. return -1;
  593. }
  594. WCHAR
  595. pStfGetInfFileWchar (
  596. IN HANDLE File,
  597. IN DWORD Pos,
  598. OUT PBOOL Error
  599. )
  600. /*++
  601. Routine Description:
  602. Returns the WCHAR at the specified position, or 0 if the file could
  603. not be read at that position.
  604. Two buffers are used to allow fast relative access. Memory-mapped
  605. files were NOT used because problems were introduced when the
  606. swap file started filling up during GUI mode.
  607. Arguments:
  608. File - Specifies the file to read
  609. Pos - Specifies the 32-bit file offset to read (zero-based, in bytes)
  610. Error - Receives TRUE if an error was encountered, or FALSE if an
  611. error was not encountered.
  612. Return Value:
  613. The WCHAR at the specified position, or 0 if an error was encountered.
  614. (Errors are usually caused by reading past the end of the file.)
  615. If an error was encountered, the Error variable is also set to TRUE.
  616. --*/
  617. {
  618. INT c;
  619. WCHAR ch;
  620. c = pStfGetInfFileByte (File, Pos);
  621. if (c == -1 || c == 26) {
  622. *Error = TRUE;
  623. return 0;
  624. }
  625. ch = (WCHAR)c;
  626. c = pStfGetInfFileByte (File, Pos + 1);
  627. if (c == -1 || c == 26) {
  628. *Error = TRUE;
  629. return 0;
  630. }
  631. ch += c * 256;
  632. *Error = FALSE;
  633. return ch;
  634. }
  635. PCSTR
  636. pStfGetInfLineA (
  637. IN HANDLE File,
  638. IN DWORD StartPos,
  639. OUT PDWORD EndPosPtr, OPTIONAL
  640. IN OUT PGROWBUFFER LineBuf
  641. )
  642. /*++
  643. Routine Description:
  644. Returns a DBCS string supplying the line. This string can be
  645. any length and is nul-terminated. It does not include the \r or
  646. \n characters.
  647. If supplied, the EndPosPtr is updated to point to the start of
  648. the next line.
  649. Arguments:
  650. File - Specifies the file to read
  651. StartPos - Specifies the 32-bit file offset to read (zero-based, in bytes)
  652. EndPosPtr - If specified, receives the 32-bit file offset of the next
  653. line, or equal to the file size for the last line.
  654. LineBuf - Specifies a reused GROWBUFFER that the caller initializes
  655. and pStfGetInfLineA uses for line allocation. The caller is
  656. responsible for cleanup.
  657. Return Value:
  658. A pointer to the DBCS string supplying the full line (with the \r, \n or
  659. \r\n sequence stripped), or NULL if an error occurs.
  660. --*/
  661. {
  662. DWORD EndPos;
  663. INT c;
  664. PBYTE Data;
  665. DWORD Pos;
  666. DWORD ByteLen = 0;
  667. EndPos = StartPos;
  668. for (;;) {
  669. c = pStfGetInfFileByte (File, EndPos);
  670. if (c == -1 || c == 26) {
  671. break;
  672. }
  673. if (IsDBCSLeadByte ((BYTE) c)) {
  674. EndPos++;
  675. c = pStfGetInfFileByte (File, EndPos);
  676. if (c == -1 || c == 26) {
  677. break;
  678. }
  679. ByteLen++;
  680. } else {
  681. if (c == '\r' || c == '\n') {
  682. EndPos++;
  683. if (c == '\r') {
  684. c = pStfGetInfFileByte (File, EndPos);
  685. if (c == '\n') {
  686. EndPos++;
  687. }
  688. }
  689. break;
  690. }
  691. }
  692. EndPos++;
  693. ByteLen++;
  694. }
  695. //
  696. // NOTE: If you make a change here, make one below in W version
  697. //
  698. // Ctrl+Z ends the file
  699. if (c == 26) {
  700. EndPos = GetFileSize (File, NULL);
  701. }
  702. // Allocate buffer, caller frees
  703. LineBuf->End = 0;
  704. Data = GrowBuffer (LineBuf, ByteLen + 2);
  705. if (!Data) {
  706. return NULL;
  707. }
  708. // We've been successful -- copy end pos to caller's variable
  709. if (EndPosPtr) {
  710. *EndPosPtr = EndPos;
  711. }
  712. // End of file condition: zero-length, but not a blank line
  713. if (!ByteLen && c != '\r' && c != '\n') {
  714. return NULL;
  715. }
  716. // Copy line to buffer
  717. for (Pos = 0 ; Pos < ByteLen ; Pos++) {
  718. Data[Pos] = (BYTE)pStfGetInfFileByte (File, StartPos);
  719. StartPos++;
  720. }
  721. Data[Pos] = 0;
  722. Data[Pos + 1] = 0;
  723. return (PCSTR) Data;
  724. }
  725. PCWSTR
  726. pStfGetInfLineW (
  727. IN HANDLE File,
  728. IN DWORD StartPos,
  729. OUT PDWORD EndPosPtr, OPTIONAL
  730. IN OUT PGROWBUFFER LineBuf
  731. )
  732. /*++
  733. Routine Description:
  734. Returns a UNICODE string supplying the line. This string can be
  735. any length and is nul-terminated. It does not include the \r or
  736. \n characters.
  737. If supplied, the EndPosPtr is updated to point to the start of
  738. the next line.
  739. Arguments:
  740. File - Specifies the file to read
  741. StartPos - Specifies the 32-bit file offset to read (zero-based, in bytes)
  742. EndPosPtr - If specified, receives the 32-bit file offset of the next
  743. line, or equal to the file size for the last line.
  744. LineBuf - Specifies a reused GROWBUFFER that the caller initializes
  745. and pStfGetInfLineA uses for line allocation. The caller is
  746. responsible for cleanup.
  747. Return Value:
  748. A pointer to the UNICODE string supplying the full line (with the \r, \n or
  749. \r\n sequence stripped), or NULL if an error occurs.
  750. --*/
  751. {
  752. DWORD EndPos;
  753. PBYTE Data;
  754. DWORD Pos;
  755. DWORD ByteLen = 0;
  756. WCHAR ch;
  757. BOOL Error;
  758. EndPos = StartPos;
  759. for (;;) {
  760. ch = pStfGetInfFileWchar (File, EndPos, &Error);
  761. if (Error) {
  762. break;
  763. }
  764. if (ch == TEXT('\r') || ch == TEXT('\n')) {
  765. EndPos += 2;
  766. if (ch == TEXT('\r')) {
  767. ch = pStfGetInfFileWchar (File, EndPos, &Error);
  768. if (ch == '\n') {
  769. EndPos += 2;
  770. }
  771. }
  772. break;
  773. }
  774. EndPos += 2;
  775. ByteLen += 2;
  776. }
  777. //
  778. // NOTE: If you make a change here, make one above in A version
  779. //
  780. // Ctrl+Z ends the file
  781. if (ch == 26) {
  782. EndPos = GetFileSize (File, NULL);
  783. }
  784. // Allocate buffer
  785. LineBuf->End = 0;
  786. Data = GrowBuffer (LineBuf, ByteLen + 2);
  787. if (!Data) {
  788. return NULL;
  789. }
  790. // We've been successful -- copy end pos to caller's variable
  791. if (EndPosPtr) {
  792. *EndPosPtr = EndPos;
  793. }
  794. // End of file condition: zero-length, but not a blank line
  795. if (!ByteLen && ch != L'\r' && ch != L'\n') {
  796. return NULL;
  797. }
  798. // Copy to buffer
  799. for (Pos = 0 ; Pos < ByteLen ; Pos++) {
  800. Data[Pos] = (BYTE)pStfGetInfFileByte (File, StartPos);
  801. StartPos++;
  802. }
  803. Data[Pos] = 0;
  804. Data[Pos + 1] = 0;
  805. if (EndPosPtr) {
  806. *EndPosPtr = EndPos;
  807. }
  808. return (PCWSTR) Data;
  809. }
  810. PCTSTR
  811. pStfGetNextInfLine (
  812. IN HANDLE File,
  813. IN PGROWBUFFER LineBuf,
  814. IN OUT PDWORD Pos,
  815. IN BOOL UnicodeMode
  816. )
  817. /*++
  818. Routine Description:
  819. Returns a TCHAR string supplying the line. This string can be
  820. any length and is nul-terminated. It does not include the \r or
  821. \n characters.
  822. Arguments:
  823. File - Specifies the file to read
  824. LineBuf - Specifies a reused GROWBUFFER that the caller initializes
  825. and pStfGetInfLineA uses for line allocation. The caller is
  826. responsible for cleanup.
  827. Pos - Specifies the byte offset to the start of the line. Receives
  828. the byte offset to the next line.
  829. UnicodeMode - Specifies TRUE if the file being read is a UNICODE file,
  830. or FALSE if the file being read is a DBCS file.
  831. Return Value:
  832. A pointer to the TCHAR string supplying the full line (with the \r, \n or
  833. \r\n sequence stripped), or NULL if an error occurs.
  834. --*/
  835. {
  836. PCSTR AnsiStr = NULL;
  837. PCWSTR UnicodeStr = NULL;
  838. PCTSTR FinalStr;
  839. BOOL Converted = FALSE;
  840. //
  841. // Obtain the text from the file
  842. //
  843. if (UnicodeMode) {
  844. UnicodeStr = pStfGetInfLineW (File, *Pos, Pos, LineBuf);
  845. if (!UnicodeStr) {
  846. return NULL;
  847. }
  848. } else {
  849. AnsiStr = pStfGetInfLineA (File, *Pos, Pos, LineBuf);
  850. if (!AnsiStr) {
  851. return NULL;
  852. }
  853. }
  854. //
  855. // Convert to TCHAR
  856. //
  857. #ifdef UNICODE
  858. if (AnsiStr) {
  859. UnicodeStr = ConvertAtoW (AnsiStr);
  860. if (!UnicodeStr) {
  861. return NULL;
  862. }
  863. Converted = TRUE;
  864. }
  865. FinalStr = UnicodeStr;
  866. #else
  867. if (UnicodeStr) {
  868. AnsiStr = ConvertWtoA (UnicodeStr);
  869. if (!AnsiStr) {
  870. return NULL;
  871. }
  872. Converted = TRUE;
  873. }
  874. FinalStr = AnsiStr;
  875. #endif
  876. //
  877. // Copy converted string into line buffer
  878. //
  879. if (Converted) {
  880. LineBuf->End = 0;
  881. Converted = MultiSzAppend (LineBuf, FinalStr);
  882. FreeConvertedStr (FinalStr);
  883. if (!Converted) {
  884. return NULL;
  885. }
  886. }
  887. return (PCTSTR) LineBuf->Buf;
  888. }
  889. BOOL
  890. StfDeleteLineInInfSection (
  891. IN OUT PSETUPTABLE TablePtr,
  892. IN PSTFINFLINE InfLine
  893. )
  894. /*++
  895. Routine Description:
  896. DeleteLineInInfSection removes the specified InfLine from its section,
  897. cleaning up memory used by the line.
  898. Arguments:
  899. TablePtr - Specifies the table owning the INF line
  900. InfLine - Specifies the line to delete
  901. Return Value:
  902. TRUE if the line was deleted successfully, or FALSE if an error
  903. occurred.
  904. --*/
  905. {
  906. if (InfLine->Prev) {
  907. InfLine->Prev->Next = InfLine->Next;
  908. } else {
  909. InfLine->Section->FirstLine = InfLine->Next;
  910. }
  911. if (InfLine->Next) {
  912. InfLine->Next->Prev = InfLine->Prev;
  913. } else {
  914. InfLine->Section->LastLine = InfLine->Prev;
  915. }
  916. if (InfLine->Key) {
  917. PoolMemReleaseMemory (TablePtr->InfPool, (PVOID) InfLine->Key);
  918. }
  919. if (InfLine->Data) {
  920. PoolMemReleaseMemory (TablePtr->InfPool, (PVOID) InfLine->Data);
  921. }
  922. InfLine->Section->LineCount--;
  923. PoolMemReleaseMemory (TablePtr->InfPool, (PVOID) InfLine);
  924. return TRUE;
  925. }
  926. BOOL
  927. StfDeleteSectionInInfFile (
  928. IN OUT PSETUPTABLE TablePtr,
  929. IN PSTFINFSECTION Section
  930. )
  931. /*++
  932. Routine Description:
  933. DeleteSectionInInfFile removes the specified section from the INF
  934. data structure, removing all lines cleaning up
  935. memory used by the section.
  936. Arguments:
  937. TablePtr - Specifies the table owning the INF line
  938. Section - Specifies the section to delete
  939. Return Value:
  940. TRUE if the section was deleted successfully, or FALSE if an error
  941. occurred.
  942. --*/
  943. {
  944. PSTFINFLINE InfLine, DelInfLine;
  945. InfLine = Section->FirstLine;
  946. while (InfLine) {
  947. DelInfLine = InfLine;
  948. InfLine = InfLine->Next;
  949. if (!StfDeleteLineInInfSection (TablePtr, DelInfLine)) {
  950. return FALSE;
  951. }
  952. }
  953. if (Section->Prev) {
  954. Section->Prev->Next = Section->Next;
  955. } else {
  956. TablePtr->FirstInfSection = Section->Next;
  957. }
  958. if (Section->Next) {
  959. Section->Next->Prev = Section->Prev;
  960. } else {
  961. TablePtr->LastInfSection = Section->Prev;
  962. }
  963. PoolMemReleaseMemory (TablePtr->InfPool, (PVOID) Section->Name);
  964. PoolMemReleaseMemory (TablePtr->InfPool, (PVOID) Section);
  965. return TRUE;
  966. }
  967. UINT
  968. StfGetInfSectionLineCount (
  969. IN PSTFINFSECTION Section
  970. )
  971. /*++
  972. Routine Description:
  973. GetInfSectionLineCount returns the number of lines in the specified
  974. INF section.
  975. Arguments:
  976. Section - Specifies the section to query
  977. Return Value:
  978. The number of lines, or zero if the section has no lines.
  979. --*/
  980. {
  981. return Section->LineCount;
  982. }