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.

1519 lines
33 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. inf.c
  5. Abstract:
  6. Provides wrappers for commonly used INF file handling routines. The wrappers provide, amount
  7. other things, easy memory allocation using a user supplied GROWBUFFER or PMHANDLE
  8. Author:
  9. 09-Jul-1997 Marc R. Whitten (marcw) - File creation.
  10. Revision History:
  11. 22-Oct-1998 marcw Added capability to replace/append inf files.
  12. 08-Oct-1997 jimschm OEM version of SetupGetStringField
  13. --*/
  14. #include "pch.h"
  15. GROWLIST g_FileNameList;
  16. HASHTABLE g_NameTable;
  17. static INT g_InfRefs;
  18. VOID
  19. InfGlobalInit (
  20. IN BOOL Terminate
  21. )
  22. {
  23. if (!Terminate) {
  24. MYASSERT (g_InfRefs >= 0);
  25. g_InfRefs++;
  26. if (g_InfRefs == 1) {
  27. ZeroMemory (&g_FileNameList, sizeof (GROWLIST));
  28. g_NameTable = HtAllocA();
  29. }
  30. } else {
  31. MYASSERT (g_InfRefs >= 0);
  32. g_InfRefs--;
  33. if (!g_InfRefs) {
  34. GlFree (&g_FileNameList);
  35. HtFree (g_NameTable);
  36. g_NameTable = NULL;
  37. }
  38. }
  39. }
  40. VOID
  41. pAddFileRef (
  42. IN HINF InfHandle,
  43. IN PCSTR FileName
  44. )
  45. {
  46. PBYTE data;
  47. UINT size;
  48. size = sizeof (InfHandle) + SizeOfStringA (FileName);
  49. data = MemAlloc (g_hHeap, 0, size);
  50. if (data) {
  51. CopyMemory (data, &InfHandle, sizeof (InfHandle));
  52. StringCopyA ((PSTR) (data + sizeof (InfHandle)), FileName);
  53. GlAppend (&g_FileNameList, data, size);
  54. MemFree (g_hHeap, 0, data);
  55. }
  56. }
  57. PBYTE
  58. pFindFileRef (
  59. IN HINF InfHandle,
  60. OUT PUINT ListPos OPTIONAL
  61. )
  62. {
  63. UINT u;
  64. UINT count;
  65. HINF *p;
  66. count = GlGetSize (&g_FileNameList);
  67. for (u = 0 ; u < count ; u++) {
  68. p = (HINF *) GlGetItem (&g_FileNameList, u);
  69. if (*p == InfHandle) {
  70. if (ListPos) {
  71. *ListPos = u;
  72. }
  73. return (PBYTE) p;
  74. }
  75. }
  76. DEBUGMSG ((DBG_VERBOSE, "Can't find file name for INF handle 0x%08X", InfHandle));
  77. return NULL;
  78. }
  79. VOID
  80. pDelFileRef (
  81. IN HINF InfHandle
  82. )
  83. {
  84. UINT pos;
  85. if (pFindFileRef (InfHandle, &pos)) {
  86. GlDeleteItem (&g_FileNameList, pos);
  87. }
  88. }
  89. PCSTR
  90. pGetFileNameOfInf (
  91. IN HINF Inf
  92. )
  93. {
  94. PBYTE fileRef;
  95. fileRef = pFindFileRef (Inf, NULL);
  96. if (fileRef) {
  97. return (PCSTR) (fileRef + sizeof (HINF));
  98. }
  99. return NULL;
  100. }
  101. VOID
  102. InfNameHandle (
  103. IN HINF Inf,
  104. IN PCSTR NewName,
  105. IN BOOL OverwriteExistingName
  106. )
  107. {
  108. PCSTR name;
  109. HASHITEM item;
  110. if (!NewName) {
  111. pDelFileRef (Inf);
  112. return;
  113. }
  114. name = pGetFileNameOfInf (Inf);
  115. if (!OverwriteExistingName && name) {
  116. return;
  117. }
  118. if (name) {
  119. pDelFileRef (Inf);
  120. }
  121. item = HtAddStringA (g_NameTable, NewName);
  122. name = HtGetStringFromItemA (item);
  123. if (name) {
  124. pAddFileRef (Inf, name);
  125. }
  126. }
  127. PBYTE
  128. pAllocateSpace (
  129. IN PINFSTRUCT Context,
  130. IN UINT Size
  131. )
  132. /*++
  133. Routine Description:
  134. pAllocateSpace is a private function that allocates space using the user specified allocator.
  135. Arguments:
  136. Context - A valid INFSTRUCT which has been initialized either by a call to InitInfStruct or
  137. by using one of the static initializers (INITINFSTRUCT_GROWBUFFER or
  138. INITINFSTRUCT_PMHANDLE)
  139. Size - The size (in bytes) to allocate.
  140. Return Value:
  141. A pointer to the successfully allocated memory or NULL if no memory could be allocated.
  142. --*/
  143. {
  144. PBYTE rBytes = NULL;
  145. switch (Context -> Allocator) {
  146. case INF_USE_PMHANDLE:
  147. //
  148. // Allocate space using Poolmem.
  149. //
  150. rBytes = PmGetMemory(Context -> PoolHandle, Size);
  151. break;
  152. case INF_USE_GROWBUFFER:
  153. case INF_USE_PRIVATE_GROWBUFFER:
  154. //
  155. // Allocate space using Growbuf.
  156. //
  157. Context->GrowBuffer.End = 0;
  158. rBytes = GbGrow (&(Context -> GrowBuffer), Size);
  159. break;
  160. case INF_USE_PRIVATE_PMHANDLE:
  161. //
  162. // Allocate space using private growbuffer.
  163. //
  164. if (!Context -> PoolHandle) {
  165. Context -> PoolHandle = PmCreateNamedPool ("INF Pool");
  166. }
  167. if (Context -> PoolHandle) {
  168. rBytes = PmGetMemory(Context -> PoolHandle, Size);
  169. }
  170. break;
  171. }
  172. return rBytes;
  173. }
  174. VOID
  175. InitInfStruct (
  176. OUT PINFSTRUCT Context,
  177. IN PGROWBUFFER GrowBuffer, OPTIONAL
  178. IN PMHANDLE PoolHandle OPTIONAL
  179. )
  180. /*++
  181. Routine Description:
  182. This function initializes an INFSTRUCT with the user supplied allocator. It is used when
  183. user of the INF wrapper routines wishes to manage his own memory (i.e. such as when he
  184. already has a suitable allocator with sufficient scope created, etc.)
  185. There is no need to call this function if the user wishes to have the INF wrapper routines
  186. manage there own memory. Initialize your Init structure with one of either
  187. INITINFSTRUCT_POOLMEM or INITINFSTRUCT_GROWBUFFER, depending on your preference and needs
  188. for an allocator.
  189. Arguments:
  190. Context - Recieves the initialized INFSTRUCT.
  191. GrowBuffer - An optional parameter containing a user supplied and initialized GROWBUFFER.
  192. If this parameter is non-NULL, then PoolHandle should be NULL.
  193. PoolHandle - An optional parameter containing a user supplied and initialized POOLHANDLE.
  194. If this parameter is non-NULL, then GrowBuffer should be NULL.
  195. One of either GrowBuffer or PoolHandle *must* be specified.
  196. Return Value:
  197. None.
  198. --*/
  199. {
  200. ZeroMemory(Context,sizeof(INFSTRUCT));
  201. if (!PoolHandle && !GrowBuffer) {
  202. Context -> Allocator = INF_USE_PRIVATE_PMHANDLE;
  203. }
  204. if (PoolHandle) {
  205. Context -> PoolHandle = PoolHandle;
  206. Context -> Allocator = INF_USE_PMHANDLE;
  207. }
  208. if (GrowBuffer) {
  209. Context -> GrowBuffer = *GrowBuffer;
  210. Context -> Allocator = INF_USE_GROWBUFFER;
  211. }
  212. }
  213. VOID
  214. InfCleanUpInfStruct (
  215. IN OUT PINFSTRUCT Context
  216. )
  217. /*++
  218. Routine Description:
  219. InfCleanupInfStruct is responsible for cleaning up the data associated
  220. with an INFSTRUCT. This is a mandatory call, unless the INFSTRUCT
  221. was initialized with InitInfStruct, called with a non-NULL grow buffer or
  222. pool handle.
  223. This routine can be called no matter how the INFSTRUCT was initialized.
  224. However, it will NOT free caller-owned grow buffers or pools.
  225. Arguments:
  226. Context - Receives the properly cleaned up INFSTRUCT, ready to be
  227. reused.
  228. Return Value:
  229. none
  230. --*/
  231. {
  232. if (Context -> Allocator == INF_USE_PRIVATE_GROWBUFFER) {
  233. GbFree (&(Context -> GrowBuffer));
  234. }
  235. else if (Context -> Allocator == INF_USE_PRIVATE_PMHANDLE && Context -> PoolHandle) {
  236. PmEmptyPool (Context->PoolHandle);
  237. PmDestroyPool (Context -> PoolHandle);
  238. }
  239. InitInfStruct (Context, NULL, NULL);
  240. }
  241. VOID
  242. InfResetInfStruct (
  243. IN OUT PINFSTRUCT Context
  244. )
  245. /*++
  246. Routine Description:
  247. InfResetInfStruct resets the pool so memory can be recycled. The intent is
  248. to allow a caller to reset the INFSTRUCT in order to release the memory
  249. obtained from getting INF fields. This is useful in a loop of InfFindFirstLine/
  250. InfFindNextLine, where two or more fields are processed for each line.
  251. If only one field is processed in an InfFindFirstLine/InfFindNextLine loop,
  252. a grow buffer should be used instead.
  253. This routine empties the active pool block, a block that is 8K by default. If
  254. more than the block size has been allocated, other memory blocks besides the
  255. active block will exist. Because only the active block is reset, the pool will
  256. grow.
  257. If the caller expects more than the block size during one iteration, it should call
  258. InfCleanupInfStruct to free the pool completely.
  259. Arguments:
  260. Context - Specifies the struct to reset
  261. Return Value:
  262. none
  263. --*/
  264. {
  265. switch (Context -> Allocator) {
  266. case INF_USE_PMHANDLE:
  267. case INF_USE_PRIVATE_PMHANDLE:
  268. if (Context->PoolHandle) {
  269. PmEmptyPool (Context->PoolHandle);
  270. }
  271. break;
  272. //for some reason lint thought we forgot about INF_USE_GROWBUFFER and
  273. //INF_USE_PRIVATE_GROWBUFFER. This is not the case so...
  274. //lint -e(787)
  275. }
  276. }
  277. /*++
  278. Routine Description:
  279. InfOpenInfFileA and InfOpenInfFileW are wrappers for the SetupOpenInfFile function.
  280. They cut down the number of parameters necessary to open an INF file by supplying
  281. the most common options for non-user specified parameters.
  282. A call to one of these functions is equivelant to
  283. SetupOpenInfFile(<FileName>,NULL,INF_STYLE_WIN4,NULL)
  284. Arguments:
  285. FileName - Contains the name of the INF file to open. See the help for SetupOpenInfFile
  286. for special details concerning this parameter.
  287. Return Value:
  288. If the INF file is successfully opened, a valid HINF is returned, otherwise,
  289. INVALID_HANDLE_VALUE is returned. See the documentation for SetupOpenInfFile for more
  290. details.
  291. --*/
  292. HINF
  293. RealInfOpenInfFileA (
  294. IN PCSTR FileSpec /*,*/
  295. ALLOCATION_TRACKING_DEF
  296. )
  297. {
  298. HINF rInf;
  299. MYASSERT(FileSpec);
  300. //
  301. // Open the main inf.
  302. //
  303. rInf = SetupOpenInfFileA (
  304. FileSpec,
  305. NULL,
  306. INF_STYLE_WIN4 | INF_STYLE_OLDNT,
  307. NULL
  308. );
  309. DebugRegisterAllocation (INF_HANDLE, (PVOID) rInf, File, Line);
  310. pAddFileRef (rInf, FileSpec);
  311. return rInf;
  312. }
  313. HINF
  314. RealInfOpenInfFileW (
  315. IN PCWSTR FileSpec /*,*/
  316. ALLOCATION_TRACKING_DEF
  317. )
  318. {
  319. PCSTR AnsiFileSpec;
  320. HINF rInf;
  321. AnsiFileSpec = ConvertWtoA (FileSpec);
  322. MYASSERT (AnsiFileSpec);
  323. rInf = InfOpenInfFileA (AnsiFileSpec);
  324. FreeConvertedStr (AnsiFileSpec);
  325. return rInf;
  326. }
  327. VOID
  328. InfCloseInfFile (
  329. HINF Inf
  330. )
  331. {
  332. DebugUnregisterAllocation (INF_HANDLE, Inf);
  333. pDelFileRef (Inf);
  334. SetupCloseInfFile (Inf);
  335. }
  336. /*++
  337. Routine Description:
  338. InfOpenInfInAllSourcesA and InfOpenInfInAllSourcesW are special inf open routines that
  339. are capable of opening multiple versions of the same inf file that may be spread out across
  340. installation directories. The first INF file found will be opened with a call to
  341. SetupOpenInfFile. Additional files will be opened with SetupOpenAppendInfFile.
  342. Arguments:
  343. InfSpecifier - Contains the source directory indepent portion of the path to a particular inf file.
  344. For files located in the root of the source directory, this will simply be the name
  345. of the file. For files located in a sub-directory of the source directory, this will
  346. be a partial path.
  347. SourceCount - Contains the number of source directories
  348. SourceDirectories - Contains an array of all the source directories.
  349. Return Value:
  350. If any INF file is successfully opened, a valid HINF is returned, otherwise,
  351. INVALID_HANDLE_VALUE is returned. See the documentation for SetupOpenInfFile for more
  352. details.
  353. --*/
  354. HINF
  355. InfOpenInfInAllSourcesA (
  356. IN PCSTR InfSpecifier,
  357. IN DWORD SourceCount,
  358. IN PCSTR * SourceDirectories
  359. )
  360. {
  361. DWORD index;
  362. HINF rInf = INVALID_HANDLE_VALUE;
  363. PSTR curPath;
  364. BOOL atLeastOneInfOpened = FALSE;
  365. MYASSERT(InfSpecifier && SourceDirectories);
  366. //
  367. // Open all available inf files in the source directories.
  368. //
  369. for (index = 0;index < SourceCount; index++) {
  370. //
  371. // Create a path to the INF in the current source directory.
  372. //
  373. curPath = JoinPathsA(SourceDirectories[index],InfSpecifier);
  374. //
  375. // See if the INF file exists there...
  376. //
  377. if (DoesFileExistA (curPath)) {
  378. //
  379. // Open the INF file.
  380. //
  381. if (!atLeastOneInfOpened) {
  382. //
  383. // Since we have not (successfully) opened any INF file yet, use SetupOpenInfFile.
  384. //
  385. rInf = InfOpenInfFileA(curPath);
  386. atLeastOneInfOpened = rInf != INVALID_HANDLE_VALUE;
  387. if (rInf == INVALID_HANDLE_VALUE) {
  388. LOGA ((LOG_ERROR, "Error opening INF %s.", curPath));
  389. }
  390. }
  391. else {
  392. //
  393. // Open and append this INF file.
  394. //
  395. if (!SetupOpenAppendInfFileA(curPath,rInf,NULL)) {
  396. LOGA ((LOG_ERROR,"Error opening INF %s.",curPath));
  397. }
  398. }
  399. }
  400. //
  401. // Free this string.
  402. //
  403. FreePathStringA(curPath);
  404. }
  405. return rInf;
  406. }
  407. HINF
  408. InfOpenInfInAllSourcesW (
  409. IN PCWSTR InfSpecifier,
  410. IN DWORD SourceCount,
  411. IN PCWSTR *SourceDirectories
  412. )
  413. {
  414. DWORD index;
  415. HINF rInf = INVALID_HANDLE_VALUE;
  416. PWSTR curPath;
  417. BOOL atLeastOneInfOpened = FALSE;
  418. PCSTR AnsiPath;
  419. MYASSERT(InfSpecifier && SourceDirectories);
  420. //
  421. // Open all available inf files in the source directories.
  422. //
  423. for (index = 0;index < SourceCount; index++) {
  424. //
  425. // Create a path to the INF in the current source directory.
  426. //
  427. curPath = JoinPathsW(SourceDirectories[index],InfSpecifier);
  428. //
  429. // See if the INF file exists there...
  430. //
  431. if (DoesFileExistW (curPath)) {
  432. //
  433. // Open the INF file.
  434. //
  435. if (!atLeastOneInfOpened) {
  436. //
  437. // Since we have not (successfully) opened any INF file yet, use SetupOpenInfFile.
  438. //
  439. rInf = InfOpenInfFileW(curPath);
  440. atLeastOneInfOpened = rInf != INVALID_HANDLE_VALUE;
  441. if (rInf == INVALID_HANDLE_VALUE) {
  442. LOGW ((LOG_ERROR, "OpenInfInAllSources: Error opening INF %s.", curPath));
  443. }
  444. }
  445. else {
  446. //
  447. // Open and append this INF file.
  448. //
  449. if (!SetupOpenAppendInfFileW(curPath,rInf,NULL)) {
  450. LOGW ((LOG_ERROR,"OpenInfInAllSources: Error opening INF %s.",curPath));
  451. }
  452. }
  453. }
  454. //
  455. // Free this string.
  456. //
  457. FreePathStringW(curPath);
  458. }
  459. return rInf;
  460. }
  461. /*++
  462. Routine Description:
  463. InfGetLineTextA and InfGetLineTextW are wrappers for the SetupGetLineText function.
  464. They both reduce the number of parameters required to get the line text and
  465. take care of allocating and filling a buffer with the data returned from the API.
  466. Arguments:
  467. Context - A valid InfStruct. The INFCONTEXT member of the structure must point to a valid
  468. line to retrieve (i.e. through the use of InfFindFirstLine/InfFindNextLine.
  469. Return Value:
  470. A pointer to the allocated line or NULL if there was an error. Consult GetLastError() for
  471. extended error information.
  472. --*/
  473. PSTR
  474. InfGetLineTextA (
  475. IN OUT PINFSTRUCT Context
  476. )
  477. {
  478. PSTR rLine = NULL;
  479. DWORD requiredSize;
  480. //
  481. // Get the size necessary for holding the field.
  482. //
  483. if (SetupGetLineTextA(
  484. &(Context -> Context),
  485. NULL,
  486. NULL,
  487. NULL,
  488. NULL,
  489. 0,
  490. &requiredSize
  491. )) {
  492. //
  493. // Create a string big enough.
  494. //
  495. rLine = (PSTR) pAllocateSpace(Context,requiredSize);
  496. if (rLine) {
  497. //
  498. // Get the field.
  499. //
  500. if (!SetupGetLineTextA(
  501. &(Context -> Context),
  502. NULL,
  503. NULL,
  504. NULL,
  505. rLine,
  506. requiredSize,
  507. NULL
  508. )) {
  509. //
  510. // If we did not successfully get the field, reset the string to NULL.
  511. //
  512. DEBUGMSG((DBG_ERROR,"InfGetLineTextA: Error retrieving field from INF file."));
  513. rLine = NULL;
  514. }
  515. }
  516. }
  517. return rLine;
  518. }
  519. PWSTR
  520. InfGetLineTextW (
  521. IN OUT PINFSTRUCT Context
  522. )
  523. {
  524. PWSTR rLine = NULL;
  525. DWORD requiredSize;
  526. //
  527. // Get the size necessary for holding the field.
  528. //
  529. if (SetupGetLineTextW(
  530. &(Context -> Context),
  531. NULL,
  532. NULL,
  533. NULL,
  534. NULL,
  535. 0,
  536. &requiredSize
  537. )) {
  538. //
  539. // Create a string big enough.
  540. //
  541. rLine = (PWSTR) pAllocateSpace(Context,requiredSize*sizeof(WCHAR));
  542. if (rLine) {
  543. //
  544. // Get the field.
  545. //
  546. if (!SetupGetLineTextW(
  547. &(Context -> Context),
  548. NULL,
  549. NULL,
  550. NULL,
  551. rLine,
  552. requiredSize,
  553. NULL
  554. )) {
  555. //
  556. // If we did not successfully get the field, reset the string to NULL.
  557. //
  558. DEBUGMSG((DBG_ERROR,"InfGetLineTextW: Error retrieving field from INF file."));
  559. rLine = NULL;
  560. }
  561. }
  562. }
  563. return rLine;
  564. }
  565. /*++
  566. Routine Description:
  567. InfGetMultiSzFieldA and InfGetMultiSzFieldW are wrappers for the SetupGetMultiSzField function.
  568. They both reduce the number of parameters required to get the line text and
  569. take care of allocating and filling a buffer with the data returned from the API.
  570. Arguments:
  571. Context - A valid InfStruct. The INFCONTEXT member of the structure must point to a valid
  572. line to retrieve (i.e. through the use of InfFindFirstLine/InfFindNextLine.
  573. FieldIndex - The index within the line to retrieve a string field.
  574. Return Value:
  575. A pointer to the allocated fields or NULL if there was an error. Consult GetLastError() for
  576. extended error information.
  577. --*/
  578. PSTR
  579. InfGetMultiSzFieldA (
  580. IN OUT PINFSTRUCT Context,
  581. IN UINT FieldIndex
  582. )
  583. {
  584. DWORD requiredSize;
  585. PSTR rFields = NULL;
  586. //
  587. // Get the size necessary for holding the field.
  588. //
  589. if (SetupGetMultiSzFieldA(
  590. &(Context -> Context),
  591. FieldIndex,
  592. NULL,
  593. 0,
  594. &requiredSize
  595. )) {
  596. //
  597. // Create a string big enough.
  598. //
  599. rFields = (PSTR) pAllocateSpace(Context,requiredSize);
  600. if (rFields) {
  601. //
  602. // Get the field.
  603. //
  604. if (!SetupGetMultiSzFieldA(
  605. &(Context -> Context),
  606. FieldIndex,
  607. rFields,
  608. requiredSize,
  609. NULL
  610. )) {
  611. //
  612. // If we did not successfully get the field, reset the string to NULL.
  613. //
  614. DEBUGMSG((DBG_ERROR,"InfGetMultiSzFieldA: Error retrieving field from INF file."));
  615. rFields = NULL;
  616. }
  617. }
  618. }
  619. return rFields;
  620. }
  621. PWSTR
  622. InfGetMultiSzFieldW (
  623. IN OUT PINFSTRUCT Context,
  624. IN UINT FieldIndex
  625. )
  626. {
  627. DWORD requiredSize;
  628. PWSTR rFields = NULL;
  629. //
  630. // Get the size necessary for holding the field.
  631. //
  632. if (SetupGetMultiSzFieldW(
  633. &(Context -> Context),
  634. FieldIndex,
  635. NULL,
  636. 0,
  637. &requiredSize
  638. )) {
  639. //
  640. // Create a string big enough.
  641. //
  642. rFields = (PWSTR) pAllocateSpace(Context,requiredSize*sizeof(WCHAR));
  643. if (rFields) {
  644. //
  645. // Get the field.
  646. //
  647. if (!SetupGetMultiSzFieldW(
  648. &(Context -> Context),
  649. FieldIndex,
  650. rFields,
  651. requiredSize,
  652. NULL
  653. )) {
  654. //
  655. // If we did not successfully get the field, reset the string to NULL.
  656. //
  657. DEBUGMSG((DBG_ERROR,"InfGetMultiSzFieldW: Error retrieving field from INF file."));
  658. rFields = NULL;
  659. }
  660. }
  661. }
  662. return rFields;
  663. }
  664. /*++
  665. Routine Description:
  666. InfGetStringFieldA and InfGetStringFieldW are wrappers for the SetupGetStringField function.
  667. They both reduce the number of parameters required to get the line text and
  668. take care of allocating and filling a buffer with the data returned from the API.
  669. Arguments:
  670. Context - A valid InfStruct. The INFCONTEXT member of the structure must point to a valid
  671. line to retrieve (i.e. through the use of InfFindFirstLine/InfFindNextLine.
  672. FieldIndex - The index within the line to retrieve a string field.
  673. Return Value:
  674. A pointer to the allocated line or NULL if there was an error. Consult GetLastError() for
  675. extended error information.
  676. --*/
  677. PSTR
  678. InfGetStringFieldA (
  679. IN OUT PINFSTRUCT Context,
  680. IN UINT FieldIndex
  681. )
  682. {
  683. DWORD requiredSize;
  684. PSTR rField = NULL;
  685. //
  686. // Get the size necessary for holding the field.
  687. //
  688. if (SetupGetStringFieldA(
  689. &(Context -> Context),
  690. FieldIndex,
  691. NULL,
  692. 0,
  693. &requiredSize
  694. )) {
  695. //
  696. // Create a string big enough.
  697. //
  698. rField = (PSTR) pAllocateSpace(Context,requiredSize);
  699. if (rField) {
  700. //
  701. // Get the field.
  702. //
  703. if (!SetupGetStringFieldA(
  704. &(Context -> Context),
  705. FieldIndex,
  706. rField,
  707. requiredSize,
  708. NULL
  709. )) {
  710. //
  711. // If we did not successfully get the field, reset the string to NULL.
  712. //
  713. DEBUGMSG((DBG_ERROR,"InfGetStringFieldA: Error retrieving field from INF file."));
  714. rField = NULL;
  715. }
  716. }
  717. }
  718. return rField;
  719. }
  720. PWSTR
  721. InfGetStringFieldW (
  722. IN OUT PINFSTRUCT Context,
  723. IN UINT FieldIndex
  724. )
  725. {
  726. DWORD requiredSize;
  727. PWSTR rField = NULL;
  728. //
  729. // Get the size necessary for holding the field.
  730. //
  731. if (SetupGetStringFieldW(
  732. &(Context -> Context),
  733. FieldIndex,
  734. NULL,
  735. 0,
  736. &requiredSize
  737. )) {
  738. //
  739. // Create a string big enough.
  740. //
  741. rField = (PWSTR) pAllocateSpace(Context,requiredSize*sizeof(WCHAR));
  742. if (rField) {
  743. //
  744. // Get the field.
  745. //
  746. if (!SetupGetStringFieldW(
  747. &(Context -> Context),
  748. FieldIndex,
  749. rField,
  750. requiredSize,
  751. NULL
  752. )) {
  753. //
  754. // If we did not successfully get the field, reset the string to NULL.
  755. //
  756. DEBUGMSG((DBG_ERROR,"InfGetStringFieldW: Error retrieving field from INF file."));
  757. rField = NULL;
  758. }
  759. }
  760. }
  761. return rField;
  762. }
  763. BOOL
  764. InfGetIntField (
  765. IN PINFSTRUCT Context,
  766. IN UINT FieldIndex,
  767. IN PINT Value
  768. )
  769. /*++
  770. Routine Description:
  771. InfGetIntField is a wrapper for SetupGetIntField. It is virtually identical to this function
  772. except that it takes care of getting the INFCONTEXT out of the INFSTRUCT structure.
  773. Arguments:
  774. Context - A valid InfStruct. The INFCONTEXT member of the structure must point to a valid
  775. line to retrieve (i.e. through the use of InfFindFirstLine/InfFindNextLine.
  776. FieldIndex - The index within the line from which to retrieve the field.
  777. Value - Recieves the value of the requested Int field.
  778. Return Value:
  779. TRUE if the field was successfully retrieved, FALSE otherwise. Use GetLastError() To receive
  780. extended error information.
  781. --*/
  782. {
  783. return SetupGetIntField (&(Context -> Context), FieldIndex, Value);
  784. }
  785. PBYTE
  786. InfGetBinaryField (
  787. IN PINFSTRUCT Context,
  788. IN UINT FieldIndex
  789. )
  790. /*++
  791. Routine Description:
  792. InfGetBinaryField is a wrapper for the SetupGetBinaryField function. It reduces
  793. the number of parameters required to get the line text and takes care of
  794. allocating and filling a buffer with the data returned from the API.
  795. Arguments:
  796. Context - A valid InfStruct. The INFCONTEXT member of the structure must point to a valid
  797. line to retrieve (i.e. through the use of InfFindFirstLine/InfFindNextLine.
  798. FieldIndex - the index within the line of the desired binary information.
  799. Return Value:
  800. A pointer to the allocated line or NULL if there was an error. Consult GetLastError() for
  801. extended error information.
  802. --*/
  803. {
  804. DWORD requiredSize;
  805. PBYTE rField = NULL;
  806. //
  807. // Get the size necessary for holding the field.
  808. //
  809. if (SetupGetBinaryField(
  810. &(Context -> Context),
  811. FieldIndex,
  812. NULL,
  813. 0,
  814. &requiredSize
  815. )) {
  816. //
  817. // Create a string big enough.
  818. //
  819. rField = pAllocateSpace(Context,requiredSize);
  820. if (rField) {
  821. //
  822. // Get the field.
  823. //
  824. if (!SetupGetBinaryField(
  825. &(Context -> Context),
  826. FieldIndex,
  827. rField,
  828. requiredSize,
  829. NULL
  830. )) {
  831. //
  832. // If we did not successfully get the field, reset the string to NULL.
  833. //
  834. DEBUGMSG((DBG_ERROR,"InfGetBinaryField: Error retrieving field from INF file."));
  835. rField = NULL;
  836. }
  837. }
  838. }
  839. return rField;
  840. }
  841. /*++
  842. Routine Description:
  843. InfGetIndexByLine is a straight wrapper for SetupGetLineByIndex. The only
  844. difference is the use of an PINFSTRUCT instead of a PINFCONTEXT.
  845. Arguments:
  846. InfHandle - Contains a valid HINF.
  847. Section - Contains the name of the section within the InfFile.
  848. Index - Contains the index within the section of the line in question.
  849. Context - A valid InfStruct that is updated with the result of these calls.
  850. Return Value:
  851. TRUE if the function was called successfully, FALSE otherwise.
  852. --*/
  853. BOOL
  854. InfGetLineByIndexA(
  855. IN HINF InfHandle,
  856. IN PCSTR Section,
  857. IN DWORD Index,
  858. OUT PINFSTRUCT Context
  859. )
  860. {
  861. return SetupGetLineByIndexA(InfHandle,Section,Index,&(Context -> Context));
  862. }
  863. BOOL
  864. InfGetLineByIndexW(
  865. IN HINF InfHandle,
  866. IN PCWSTR Section,
  867. IN DWORD Index,
  868. OUT PINFSTRUCT Context
  869. )
  870. {
  871. return SetupGetLineByIndexW(InfHandle,Section,Index,&(Context -> Context));
  872. }
  873. /*++
  874. Routine Description:
  875. InfFindFirstLineA and InfFindFirstLineW are wrappers for the SetupFindFirstLine function.
  876. They are virtually identical except that they operate on INFSTRUCTs instead of INFCONTEXTS.
  877. Arguments:
  878. InfHandle - Contains a valid HINF.
  879. Section - Contains the name of the section within the InfFile.
  880. Key - An optional parameter containing the name of the key within the section to find.
  881. If NULL, these routines will return the first line in the section.
  882. Context - A valid InfStruct that is updated with the result of these calls.
  883. Return Value:
  884. TRUE if lines exist in the section, FALSE otherwise.
  885. --*/
  886. BOOL
  887. InfFindFirstLineA (
  888. IN HINF InfHandle,
  889. IN PCSTR Section,
  890. IN PCSTR Key, OPTIONAL
  891. OUT PINFSTRUCT Context
  892. )
  893. {
  894. return SetupFindFirstLineA (
  895. InfHandle,
  896. Section,
  897. Key,
  898. &(Context -> Context)
  899. );
  900. }
  901. BOOL
  902. InfFindFirstLineW (
  903. IN HINF InfHandle,
  904. IN PCWSTR Section,
  905. IN PCWSTR Key,
  906. OUT PINFSTRUCT Context
  907. )
  908. {
  909. return SetupFindFirstLineW (
  910. InfHandle,
  911. Section,
  912. Key,
  913. &(Context -> Context)
  914. );
  915. }
  916. /*++
  917. Routine Description:
  918. InfFindNextLineA and InfFindNextLineW are wrappers for the SetupFindFirstLine function.
  919. They are virtually identical except that they operate on INFSTRUCTs instead of INFCONTEXTS and
  920. need only one INFSTRUCT parameter.
  921. Arguments:
  922. Context - A valid InfStruct that is updated with the result of these calls.
  923. Return Value:
  924. TRUE if there is another line in the section, FALSE otherwise.
  925. --*/
  926. BOOL
  927. InfFindNextLine (
  928. IN OUT PINFSTRUCT Context
  929. )
  930. {
  931. return SetupFindNextLine (&(Context -> Context),&(Context -> Context));
  932. }
  933. UINT
  934. InfGetFieldCount (
  935. IN PINFSTRUCT Context
  936. )
  937. {
  938. return SetupGetFieldCount(&(Context -> Context));
  939. }
  940. PCSTR
  941. InfGetOemStringFieldA (
  942. IN PINFSTRUCT Context,
  943. IN UINT Field
  944. )
  945. /*++
  946. Routine Description:
  947. InfGetOemStringField returns a string field in the OEM character set.
  948. This routine is used when accessing txtsetup.sif. It is implemented
  949. only in the A version because UNICODE does not have a concept of OEM
  950. characters.
  951. Arguments:
  952. Context - Specifies the initialized INF structure that points to the
  953. line to read from
  954. Field - Specifies the field number
  955. Return Value:
  956. A pointer to the OEM string, or NULL if an error occurred.
  957. --*/
  958. {
  959. PCSTR Text;
  960. PSTR OemText;
  961. UINT Size;
  962. Text = InfGetStringFieldA (Context, Field);
  963. if (!Text) {
  964. return NULL;
  965. }
  966. Size = SizeOfStringA (Text);
  967. OemText = (PSTR) pAllocateSpace (Context, Size);
  968. if (!OemText) {
  969. return NULL;
  970. }
  971. //
  972. // We leave Text allocated because the caller will free everything
  973. // when they clean up Context. Note the assumption that the conversion
  974. // doesn't change string length.
  975. //
  976. OemToCharBuffA (Text, OemText, Size);
  977. return OemText;
  978. }
  979. BOOL
  980. SetupGetOemStringFieldA (
  981. IN PINFCONTEXT Context,
  982. IN DWORD Index,
  983. IN PSTR ReturnBuffer, OPTIONAL
  984. IN DWORD ReturnBufferSize,
  985. OUT PDWORD RequiredSize OPTIONAL
  986. )
  987. /*++
  988. Routine Description:
  989. SetupGetOemStringFieldA is a SetupGetStringField that converts the
  990. return text to the OEM character set.
  991. Arguments:
  992. Context - Specifies the initialized INF structure that points to the
  993. line to read from
  994. Index - Specifies the field number
  995. ReturnBuffer - Specifies the buffer to fill the text into
  996. ReturnBufferSize - Specifies the size of ReturnBuffer in bytes
  997. RequiredSize - Receives the size of the buffer needed
  998. Return Value:
  999. TRUE if successful, FALSE if failure.
  1000. --*/
  1001. {
  1002. PSTR OemBuf;
  1003. UINT Size;
  1004. if (!SetupGetStringFieldA (
  1005. Context,
  1006. Index,
  1007. ReturnBuffer,
  1008. ReturnBufferSize,
  1009. RequiredSize
  1010. )) {
  1011. return FALSE;
  1012. }
  1013. if (!ReturnBuffer) {
  1014. return TRUE;
  1015. }
  1016. Size = SizeOfStringA (ReturnBuffer);
  1017. OemBuf = (PSTR) MemAlloc (g_hHeap, 0, Size);
  1018. OemToCharBuffA (ReturnBuffer, OemBuf, Size);
  1019. StringCopyA (ReturnBuffer, OemBuf);
  1020. MemFree (g_hHeap, 0, OemBuf);
  1021. return TRUE;
  1022. }
  1023. VOID
  1024. InfLogContext (
  1025. IN PCSTR LogType,
  1026. IN HINF InfHandle,
  1027. IN PINFSTRUCT InfStruct
  1028. )
  1029. {
  1030. PCSTR fileName;
  1031. PSTR field0 = NULL;
  1032. PSTR field1 = NULL;
  1033. PSTR lineData;
  1034. UINT requiredSize;
  1035. //
  1036. // Log the file name, if one exists
  1037. //
  1038. fileName = pGetFileNameOfInf (InfHandle);
  1039. if (fileName) {
  1040. LOGA ((
  1041. LogType,
  1042. "%s",
  1043. fileName
  1044. ));
  1045. }
  1046. //
  1047. // Get field 0
  1048. //
  1049. if (SetupGetStringFieldA(
  1050. &InfStruct->Context,
  1051. 0,
  1052. NULL,
  1053. 0,
  1054. &requiredSize
  1055. )) {
  1056. field0 = (PSTR) MemAlloc (g_hHeap, 0, requiredSize);
  1057. if (!SetupGetStringFieldA(
  1058. &InfStruct->Context,
  1059. 0,
  1060. field0,
  1061. requiredSize,
  1062. NULL
  1063. )) {
  1064. MemFree (g_hHeap, 0, field0);
  1065. field0 = NULL;
  1066. }
  1067. }
  1068. //
  1069. // Get field 1
  1070. //
  1071. if (SetupGetStringFieldA(
  1072. &InfStruct->Context,
  1073. 1,
  1074. NULL,
  1075. 0,
  1076. &requiredSize
  1077. )) {
  1078. field1 = (PSTR) MemAlloc (g_hHeap, 0, requiredSize);
  1079. if (!SetupGetStringFieldA(
  1080. &InfStruct->Context,
  1081. 1,
  1082. field1,
  1083. requiredSize,
  1084. NULL
  1085. )) {
  1086. MemFree (g_hHeap, 0, field1);
  1087. field1 = NULL;
  1088. }
  1089. }
  1090. //
  1091. // Compare them, and if they are the same, eliminate field 0
  1092. //
  1093. if (field0 && field1) {
  1094. if (StringMatchA (field0, field1)) {
  1095. MemFree (g_hHeap, 0, field0);
  1096. field0 = NULL;
  1097. }
  1098. }
  1099. //
  1100. // Now print the entire line
  1101. //
  1102. if (SetupGetLineTextA (
  1103. &InfStruct->Context,
  1104. NULL,
  1105. NULL,
  1106. NULL,
  1107. NULL,
  1108. 0,
  1109. &requiredSize
  1110. )) {
  1111. lineData = (PSTR) MemAlloc (g_hHeap, 0, requiredSize);
  1112. if (SetupGetLineTextA (
  1113. &InfStruct->Context,
  1114. NULL,
  1115. NULL,
  1116. NULL,
  1117. lineData,
  1118. requiredSize,
  1119. NULL
  1120. )) {
  1121. if (field0) {
  1122. LOGA ((LogType, "Line: %s = %s", field0, lineData));
  1123. } else {
  1124. LOGA ((LogType, "Line: %s", lineData));
  1125. }
  1126. MemFree (g_hHeap, 0, lineData);
  1127. }
  1128. }
  1129. if (field0) {
  1130. MemFree (g_hHeap, 0, field0);
  1131. }
  1132. if (field1) {
  1133. MemFree (g_hHeap, 0, field1);
  1134. }
  1135. }