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.

1721 lines
41 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. hwdb.c
  5. Abstract:
  6. PNP device manipulation routines.
  7. Adapted from the win95upg project.
  8. Author:
  9. Ovidiu Temereanca (ovidiut) 02-Jul-2000 Initial implementation
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #define DBG_HWDB "Hwdb"
  14. static HANDLE g_hHeap = NULL;
  15. static PCSTR g_TempDir = NULL;
  16. #define HWCOMPDAT_SIGNATURE "HwCompDat-v2"
  17. #define MAX_PNPID 1024
  18. #ifdef DEBUG
  19. extern BOOL g_DoLog;
  20. extern BOOL g_ResetLog;
  21. #endif
  22. typedef struct {
  23. HANDLE File;
  24. HASHITEM InfFileOffset;
  25. BOOL UnsupportedDevice;
  26. PHWDB Hwbd;
  27. } SAVE_ENUM_PARAMS, *PSAVE_ENUM_PARAMS;
  28. //
  29. // REM - g_ExcludedInfs was removed because hwdb will be used for any 3rd party driver files
  30. // and we need to make suer ALL infs are scanned
  31. //
  32. //
  33. // Implementation
  34. //
  35. BOOL
  36. HwdbpInitialize (
  37. IN PCSTR TempDir
  38. )
  39. {
  40. BOOL b = TRUE;
  41. //
  42. // only initialize data once
  43. //
  44. if (g_hHeap) {
  45. DEBUGMSG ((
  46. DBG_WARNING,
  47. "HwdbpInitialize: called when the module was already initialized - this call will be ignored"
  48. ));
  49. return TRUE;
  50. }
  51. g_hHeap = HeapCreate (0, 65536, 0);
  52. if (!g_hHeap) {
  53. b = FALSE;
  54. }
  55. if (b) {
  56. #ifdef DEBUG
  57. g_DoLog = TRUE;
  58. g_ResetLog = TRUE;
  59. #endif
  60. UtInitialize (g_hHeap);
  61. if (TempDir) {
  62. g_TempDir = DuplicateText (TempDir);
  63. if (g_TempDir == NULL) {
  64. b = FALSE;
  65. }
  66. }
  67. }
  68. if (!b) {
  69. HwdbpTerminate ();
  70. }
  71. return b;
  72. }
  73. VOID
  74. HwdbpTerminate (
  75. VOID
  76. )
  77. {
  78. if (g_TempDir) {
  79. FreeText (g_TempDir);
  80. g_TempDir = NULL;
  81. }
  82. UtTerminate ();
  83. if (g_hHeap) {
  84. HeapDestroy (g_hHeap);
  85. g_hHeap = NULL;
  86. }
  87. }
  88. BOOL
  89. pReadDword (
  90. IN HANDLE File,
  91. OUT PDWORD Data
  92. )
  93. /*++
  94. Routine Description:
  95. pReadDword reads the next DWORD at the current file position of File.
  96. Arguments:
  97. File - Specifies file to read
  98. Data - Receives the DWORD
  99. Return Value:
  100. TRUE if the function completes successfully, or FALSE if it fails.
  101. Call GetLastError for additional failure information.
  102. --*/
  103. {
  104. DWORD BytesRead;
  105. return ReadFile (File, Data, sizeof (DWORD), &BytesRead, NULL) &&
  106. BytesRead == sizeof (DWORD);
  107. }
  108. BOOL
  109. pReadWord (
  110. IN HANDLE File,
  111. OUT PWORD Data
  112. )
  113. /*++
  114. Routine Description:
  115. pReadWord reads the next WORD at the current file position of File.
  116. Arguments:
  117. File - Specifies file to read
  118. Data - Receive s the WORD
  119. Return Value:
  120. TRUE if the function completes successfully, or FALSE if it fails.
  121. Call GetLastError for additional failure information.
  122. --*/
  123. {
  124. DWORD BytesRead;
  125. return ReadFile (File, Data, sizeof (WORD), &BytesRead, NULL) &&
  126. BytesRead == sizeof (WORD);
  127. }
  128. BOOL
  129. pReadString (
  130. IN HANDLE File,
  131. OUT PTSTR Buf,
  132. IN DWORD BufSizeInBytes
  133. )
  134. /*++
  135. Routine Description:
  136. pReadString reads a WORD length from File, and then reads in the
  137. string from File.
  138. Arguments:
  139. File - Specifies file to read
  140. Buf - Receives the zero-terminated string
  141. BufSizeInBytes - Specifies the size of Buf in bytes
  142. Return Value:
  143. TRUE if the function completes successfully, or FALSE if it fails.
  144. This function will fail if the string is larger than Buf.
  145. Call GetLastError for additional failure information.
  146. --*/
  147. {
  148. DWORD BytesRead;
  149. WORD Length;
  150. MYASSERT (BufSizeInBytes);
  151. if (!BufSizeInBytes) {
  152. return FALSE;
  153. }
  154. if (!pReadWord (File, &Length)) {
  155. return FALSE;
  156. }
  157. if ((Length + 1 ) * sizeof (CHAR) > BufSizeInBytes) {
  158. return FALSE;
  159. }
  160. if (Length) {
  161. if (!ReadFile (File, Buf, Length, &BytesRead, NULL) ||
  162. Length != BytesRead
  163. ) {
  164. return FALSE;
  165. }
  166. }
  167. Buf[Length] = 0;
  168. return TRUE;
  169. }
  170. BOOL
  171. pWriteDword (
  172. IN HANDLE File,
  173. IN DWORD Val
  174. )
  175. /*++
  176. Routine Description:
  177. pWriteDword writes the specified DWORD value to File.
  178. Arguments:
  179. File - Specifies file to write to
  180. Val - Specifies value to write
  181. Return Value:
  182. TRUE if the function completes successfully, or FALSE if it fails.
  183. Call GetLastError for additional failure information.
  184. --*/
  185. {
  186. DWORD bytesWritten;
  187. return WriteFile (File, &Val, sizeof (Val), &bytesWritten, NULL) &&
  188. bytesWritten == sizeof (Val);
  189. }
  190. BOOL
  191. pWriteWord (
  192. IN HANDLE File,
  193. IN WORD Val
  194. )
  195. /*++
  196. Routine Description:
  197. pWriteWord writes the specified WORD vlue to File.
  198. Arguments:
  199. File - Specifies file to write to
  200. Val - Specifies value to write
  201. Return Value:
  202. TRUE if the function completes successfully, or FALSE if it fails.
  203. Call GetLastError for additional failure information.
  204. --*/
  205. {
  206. DWORD bytesWritten;
  207. return WriteFile (File, &Val, sizeof (Val), &bytesWritten, NULL) &&
  208. bytesWritten == sizeof (Val);
  209. }
  210. BOOL
  211. pWriteString (
  212. IN HANDLE File,
  213. IN PCSTR String
  214. )
  215. /*++
  216. Routine Description:
  217. pWriteString writes a string to a File
  218. Arguments:
  219. File - Specifies file to write to
  220. String - Specifies the zero-terminated string
  221. Return Value:
  222. TRUE if the function completes successfully, or FALSE if it fails.
  223. Call GetLastError for additional failure information.
  224. --*/
  225. {
  226. DWORD bytesWritten;
  227. DWORD Length;
  228. PCSTR End;
  229. BOOL b = TRUE;
  230. Length = lstrlen (String);
  231. if (Length > 0xffff) {
  232. SetLastError (ERROR_INTERNAL_ERROR);
  233. DEBUGMSG ((DBG_ERROR, "pWriteString: string too long!"));
  234. return FALSE;
  235. }
  236. b = pWriteWord (File, (WORD)Length);
  237. if (b && Length) {
  238. b = WriteFile (File, String, Length, &bytesWritten, NULL) &&
  239. Length == bytesWritten;
  240. }
  241. return b;
  242. }
  243. PHWDB
  244. HwdbpOpen (
  245. IN PCSTR DatabaseFile OPTIONAL
  246. )
  247. {
  248. CHAR buffer[MAX_PATH];
  249. CHAR infFile[MAX_MBCHAR_PATH];
  250. CHAR pnpId[1024];
  251. CHAR sig[sizeof (HWCOMPDAT_SIGNATURE)];
  252. DWORD rc;
  253. HANDLE file = INVALID_HANDLE_VALUE;
  254. PHWDB phwdb;
  255. DWORD BytesRead;
  256. HASHITEM infOffset, result;
  257. BOOL b = FALSE;
  258. __try {
  259. phwdb = (PHWDB) MemAlloc (g_hHeap, 0, sizeof (*phwdb));
  260. if (!phwdb) {
  261. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  262. __leave;
  263. }
  264. ZeroMemory (phwdb, sizeof (*phwdb));
  265. //
  266. // Create hash tables
  267. //
  268. phwdb->InfFileTable = HtAlloc ();
  269. phwdb->PnpIdTable = HtAllocWithData (sizeof (HASHITEM*));
  270. phwdb->UnsupPnpIdTable = HtAllocWithData (sizeof (HASHITEM*));
  271. if (!phwdb->InfFileTable || !phwdb->PnpIdTable || !phwdb->UnsupPnpIdTable) {
  272. __leave;
  273. }
  274. if (DatabaseFile) {
  275. if (!GetFullPathNameA (DatabaseFile, MAX_PATH, buffer, NULL)) {
  276. __leave;
  277. }
  278. //
  279. // Try to open the file
  280. //
  281. file = CreateFileA (
  282. buffer,
  283. GENERIC_READ,
  284. FILE_SHARE_READ, // share for read access
  285. NULL, // no security attribs
  286. OPEN_EXISTING,
  287. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  288. NULL // no template
  289. );
  290. if (file == INVALID_HANDLE_VALUE) {
  291. __leave;
  292. }
  293. //
  294. // Look at the signature
  295. //
  296. ZeroMemory (sig, sizeof(sig));
  297. if (!ReadFile (file, sig, sizeof (HWCOMPDAT_SIGNATURE) - 1, &BytesRead, NULL) ||
  298. lstrcmpA (HWCOMPDAT_SIGNATURE, sig)
  299. ) {
  300. SetLastError (ERROR_BAD_FORMAT);
  301. __leave;
  302. }
  303. //
  304. // Get INF checksum
  305. //
  306. if (!pReadDword (file, &phwdb->Checksum)) {
  307. SetLastError (ERROR_BAD_FORMAT);
  308. __leave;
  309. }
  310. //
  311. // Read in all PNP IDs
  312. //
  313. for (;;) {
  314. //
  315. // Get INF file name. If empty, we are done.
  316. //
  317. if (!pReadString (file, infFile, sizeof (infFile))) {
  318. SetLastError (ERROR_BAD_FORMAT);
  319. __leave;
  320. }
  321. if (*infFile == 0) {
  322. break;
  323. }
  324. infOffset = HtAddString (phwdb->InfFileTable, infFile);
  325. //
  326. // Read in all PNP IDs for the INF
  327. //
  328. for (;;) {
  329. //
  330. // Get the PNP ID. If empty, we are done.
  331. //
  332. if (!pReadString (file, pnpId, sizeof (pnpId))) {
  333. SetLastError (ERROR_BAD_FORMAT);
  334. __leave;
  335. }
  336. if (*pnpId == 0) {
  337. break;
  338. }
  339. //
  340. // Add to hash table
  341. //
  342. if (*pnpId == '!') {
  343. result = HtAddStringEx (phwdb->UnsupPnpIdTable, pnpId + 1, &infOffset, CASE_INSENSITIVE);
  344. } else {
  345. result = HtAddStringEx (phwdb->PnpIdTable, pnpId, &infOffset, CASE_INSENSITIVE);
  346. }
  347. if (!result) {
  348. __leave;
  349. }
  350. }
  351. }
  352. }
  353. b = TRUE;
  354. }
  355. __finally {
  356. rc = GetLastError ();
  357. if (file != INVALID_HANDLE_VALUE) {
  358. CloseHandle (file);
  359. }
  360. if (!b && phwdb) {
  361. if (phwdb->InfFileTable) {
  362. HtFree (phwdb->InfFileTable);
  363. }
  364. if (phwdb->PnpIdTable) {
  365. HtFree (phwdb->PnpIdTable);
  366. }
  367. if (phwdb->UnsupPnpIdTable) {
  368. HtFree (phwdb->UnsupPnpIdTable);
  369. }
  370. MemFree (g_hHeap, 0, phwdb);
  371. }
  372. SetLastError (rc);
  373. }
  374. return phwdb;
  375. }
  376. /*
  377. BOOL
  378. pWriteHashTableString (
  379. IN HASHTABLE HashTable,
  380. IN HASHITEM Index,
  381. IN PCSTR String,
  382. IN PVOID ExtraData,
  383. IN UINT ExtraDataSize,
  384. IN LPARAM lParam
  385. )
  386. {
  387. MYASSERT (String && *String);
  388. return pWriteString ((HANDLE)lParam, String);
  389. }
  390. */
  391. BOOL
  392. pSavePnpID (
  393. IN HASHTABLE Table,
  394. IN HASHITEM StringId,
  395. IN PCSTR String,
  396. IN PVOID ExtraData,
  397. IN UINT ExtraDataSize,
  398. IN LPARAM lParam
  399. )
  400. /*++
  401. Routine Description:
  402. pSavePnpID is a string table callback function that writes a PNP
  403. ID to the file indicated in the params struct (the lParam argument).
  404. This function only writes PNP IDs for a specific INF file (indicated
  405. by the ExtraData arg).
  406. Arguments:
  407. Table - Specifies table being enumerated
  408. StringId - Specifies offset of string in Table
  409. String - Specifies string being enumerated
  410. ExtraData - Specifies a pointer to a LONG that holds the INF ID
  411. to enumerate. The PNP ID's INF ID must match this
  412. parameter.
  413. lParam - Specifies a pointer to a SAVE_ENUM_PARAMS struct
  414. Return Value:
  415. TRUE if the function completes successfully, or FALSE if it fails.
  416. --*/
  417. {
  418. PSAVE_ENUM_PARAMS params;
  419. CHAR bangString[MAX_PNPID + 2];
  420. BOOL b = TRUE;
  421. params = (PSAVE_ENUM_PARAMS) lParam;
  422. if (*(HASHITEM UNALIGNED*)ExtraData == params->InfFileOffset) {
  423. //
  424. // Write this PNP ID to the file
  425. //
  426. if (params->UnsupportedDevice) {
  427. bangString[0] = '!';
  428. lstrcpy (bangString + 1, String);
  429. b = pWriteString (params->File, bangString);
  430. } else {
  431. b = pWriteString (params->File, String);
  432. }
  433. }
  434. return b;
  435. }
  436. BOOL
  437. pSaveInfWithPnpIDList (
  438. IN HASHTABLE Table,
  439. IN HASHITEM StringId,
  440. IN PCSTR String,
  441. IN PVOID ExtraData,
  442. IN UINT ExtraDataSize,
  443. IN LPARAM lParam
  444. )
  445. /*++
  446. Routine Description:
  447. pSaveInfWithPnpIDList is a string table callback function and is called for
  448. each INF in g_InfFileTable.
  449. This routine writes the name of the INF to disk, and then enumerates
  450. the PNP IDs for the INF, writing them to disk.
  451. The PNP ID list is terminated with an empty string.
  452. Arguments:
  453. Table - Specifies g_InfFileTable
  454. StringId - Specifies offset of String in g_InfFileTable
  455. String - Specifies current INF file being enumerated
  456. ExtraData - unused
  457. ExtraDataSize - unused
  458. lParam - Specifies a pointer to SAVE_ENUM_PARAMS struct.
  459. Return Value:
  460. TRUE if the function completes successfully, or FALSE if it fails.
  461. --*/
  462. {
  463. PSAVE_ENUM_PARAMS params;
  464. params = (PSAVE_ENUM_PARAMS) lParam;
  465. params->InfFileOffset = StringId;
  466. //
  467. // Save the file name
  468. //
  469. if (!pWriteString (params->File, String)) {
  470. return FALSE;
  471. }
  472. //
  473. // Enumerate all PNP IDs
  474. //
  475. params->UnsupportedDevice = FALSE;
  476. if (!EnumHashTableWithCallback (params->Hwbd->PnpIdTable, pSavePnpID, lParam)) {
  477. LOG ((LOG_ERROR, "Error while saving device list."));
  478. return FALSE;
  479. }
  480. params->UnsupportedDevice = TRUE;
  481. if (!EnumHashTableWithCallback (params->Hwbd->UnsupPnpIdTable, pSavePnpID, lParam)) {
  482. LOG ((LOG_ERROR, "Error while saving device list. (2)"));
  483. return FALSE;
  484. }
  485. //
  486. // Terminate the PNP ID list
  487. //
  488. if (!pWriteString (params->File, "")) {
  489. return FALSE;
  490. }
  491. return TRUE;
  492. }
  493. BOOL
  494. HwdbpFlush (
  495. IN PHWDB Hwdb,
  496. IN PCSTR OutputFile
  497. )
  498. {
  499. CHAR buffer[MAX_PATH];
  500. DWORD rc;
  501. HANDLE file = INVALID_HANDLE_VALUE;
  502. DWORD bytesWritten;
  503. SAVE_ENUM_PARAMS params;
  504. BOOL b = FALSE;
  505. __try {
  506. if (!OutputFile) {
  507. SetLastError (ERROR_INVALID_PARAMETER);
  508. __leave;
  509. }
  510. if (!GetFullPathNameA (OutputFile, MAX_PATH, buffer, NULL)) {
  511. __leave;
  512. }
  513. //
  514. // Try to open the file
  515. //
  516. file = CreateFileA (
  517. OutputFile,
  518. GENERIC_WRITE,
  519. 0, // no sharing
  520. NULL, // no security attribs
  521. CREATE_ALWAYS,
  522. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  523. NULL // no template
  524. );
  525. if (file == INVALID_HANDLE_VALUE) {
  526. __leave;
  527. }
  528. //
  529. // Write the signature
  530. //
  531. if (!WriteFile (file, HWCOMPDAT_SIGNATURE, sizeof (HWCOMPDAT_SIGNATURE) - 1, &bytesWritten, NULL)) {
  532. __leave;
  533. }
  534. //
  535. // Store INF checksum
  536. //
  537. if (!pWriteDword (file, Hwdb->Checksum)) {
  538. __leave;
  539. }
  540. //
  541. // Enumerate the INF table, writing the INF file name and all PNP IDs
  542. //
  543. params.File = file;
  544. params.Hwbd = Hwdb;
  545. if (!EnumHashTableWithCallback (
  546. Hwdb->InfFileTable,
  547. pSaveInfWithPnpIDList,
  548. (LPARAM) (&params)
  549. )) {
  550. DEBUGMSG ((DBG_WARNING, "SaveDeviceList: EnumHashTableWithCallback returned FALSE"));
  551. __leave;
  552. }
  553. //
  554. // end with an empty string
  555. //
  556. pWriteString (file, "");
  557. b = TRUE;
  558. }
  559. __finally {
  560. rc = GetLastError ();
  561. if (file != INVALID_HANDLE_VALUE) {
  562. CloseHandle (file);
  563. }
  564. if (!b) {
  565. DeleteFile (OutputFile);
  566. }
  567. SetLastError (rc);
  568. }
  569. return b;
  570. }
  571. BOOL
  572. HwdbpClose (
  573. IN PHWDB Hwdb
  574. )
  575. {
  576. BOOL b = FALSE;
  577. __try {
  578. if (Hwdb) {
  579. if (Hwdb->InfFileTable) {
  580. HtFree (Hwdb->InfFileTable);
  581. }
  582. if (Hwdb->PnpIdTable) {
  583. HtFree (Hwdb->PnpIdTable);
  584. }
  585. if (Hwdb->UnsupPnpIdTable) {
  586. HtFree (Hwdb->UnsupPnpIdTable);
  587. }
  588. MemFree (g_hHeap, 0, Hwdb);
  589. b = TRUE;
  590. }
  591. }
  592. __except (EXCEPTION_EXECUTE_HANDLER) {
  593. }
  594. return b;
  595. }
  596. BOOL
  597. HwpIsValidInfName (
  598. IN PCSTR FileName,
  599. OUT PTSTR UncompressedFileName,
  600. IN DWORD BufferSizeInChars
  601. )
  602. {
  603. PTSTR p;
  604. PCSTR* q;
  605. PCSTR comparationName;
  606. if (!FileName || *FileName == 0 || (DWORD)lstrlen (FileName) >= BufferSizeInChars) {
  607. MYASSERT (FALSE);
  608. return FALSE;
  609. }
  610. lstrcpyn (UncompressedFileName, FileName, BufferSizeInChars);
  611. p = _tcsdec2 (UncompressedFileName, GetEndOfString (UncompressedFileName));
  612. if (!p) {
  613. return FALSE;
  614. }
  615. if (*p == '_') {
  616. *p = 'f';
  617. comparationName = UncompressedFileName;
  618. } else {
  619. if (tolower (*p) != 'f') {
  620. return FALSE;
  621. }
  622. *UncompressedFileName = 0;
  623. comparationName = FileName;
  624. }
  625. return TRUE;
  626. }
  627. BOOL
  628. HwpAddPnpIdsInInf (
  629. IN PCSTR InfPath,
  630. IN OUT PHWDB Hwdb,
  631. IN PCSTR SourceDirectory,
  632. IN PCSTR InfFilename,
  633. IN HWDBAPPENDINFSCALLBACKA Callback, OPTIONAL
  634. IN PVOID CallbackContext, OPTIONAL
  635. IN BOOL CallbackIsUnicode
  636. )
  637. /*++
  638. Routine Description:
  639. HwpAddPnpIdsInInf scans an NT INF and places all hardware device
  640. IDs in the PNP string table.
  641. Arguments:
  642. InfPath - The path to an INF file
  643. Hwdb - Database to append PNPIDs to
  644. Return Value:
  645. TRUE if the function completes successfully, or FALSE if it fails.
  646. Call GetLastError for additional failure information.
  647. --*/
  648. {
  649. HINF inf;
  650. INFCONTEXT is;
  651. INFCONTEXT isMfg;
  652. INFCONTEXT isDev;
  653. CHAR Manufacturer[2048];
  654. CHAR DevSection[2048];
  655. CHAR pnpId[2048];
  656. BOOL UnsupportedDevice;
  657. PTSTR AppendPos;
  658. CHAR TrimmedPnpId[512];
  659. CHAR field[12];
  660. PCSTR p;
  661. LONG rc;
  662. BOOL b;
  663. PCTSTR fileName;
  664. PWSTR uInfPath = NULL;
  665. PWSTR uSourceDirectory = NULL;
  666. PWSTR uInfFilename = NULL;
  667. HASHITEM infOffset = NULL, result;
  668. BOOL Result = FALSE;
  669. //
  670. // Determine if this is an NT4 INF
  671. //
  672. inf = SetupOpenInfFile (InfPath, NULL, INF_STYLE_WIN4, NULL);
  673. if (inf == INVALID_HANDLE_VALUE) {
  674. DEBUGMSG ((DBG_ERROR, "HwpAddPnpIdsInInf: SetupOpenInfFile (%s) failed", InfPath));
  675. return FALSE;
  676. }
  677. DEBUGMSG ((DBG_HWDB, "HwpAddPnpIdsInInf: analyzing %s", InfPath));
  678. __try {
  679. //
  680. // Enumerate [Manufacturer] section
  681. //
  682. if (SetupFindFirstLine (inf, "Manufacturer", NULL, &is)) {
  683. do {
  684. //
  685. // Get the manufacturer name
  686. //
  687. if (!SetupGetLineText (&is, NULL, NULL, NULL, Manufacturer, 2048, NULL)) {
  688. DEBUGMSG ((
  689. DBG_ERROR,
  690. "HwpAddPnpIdsInInf: SetupGetLineText failed at line %u in [Manufacturer]",
  691. is.Line
  692. ));
  693. __leave;
  694. }
  695. //
  696. // Enumerate the devices listed in the manufacturer's section,
  697. // looking for PnpId
  698. //
  699. if (!SetupFindFirstLine (inf, Manufacturer, NULL, &isMfg)) {
  700. rc = GetLastError();
  701. //
  702. // if section not found, move on to next manufacturer
  703. //
  704. if (rc == ERROR_SECTION_NOT_FOUND || rc == ERROR_LINE_NOT_FOUND) {
  705. DEBUGMSG ((
  706. DBG_HWDB,
  707. "HwpAddPnpIdsInInf: Manufacturer %s section does not exist",
  708. Manufacturer
  709. ));
  710. continue;
  711. }
  712. DEBUGMSG ((
  713. DBG_ERROR,
  714. "HwpAddPnpIdsInInf: error searching for lines in [%s]",
  715. Manufacturer
  716. ));
  717. __leave;
  718. }
  719. do {
  720. if (!SetupGetStringField (&isMfg, 1, DevSection, 2048, NULL)) {
  721. DEBUGMSG ((
  722. DBG_HWDB,
  723. "HwpAddPnpIdsInInf: error retrieving first field in line %u in [%s]",
  724. isMfg.Line,
  725. DevSection
  726. ));
  727. continue;
  728. }
  729. //
  730. // Try platform-specific section first, then section.NT, then section
  731. //
  732. AppendPos = GetEndOfString (DevSection);
  733. #if defined _IA64_
  734. wsprintf (AppendPos, TEXT(".%s"), INFSTR_PLATFORM_NTIA64);
  735. #elif defined _X86_
  736. wsprintf (AppendPos, TEXT(".%s"), INFSTR_PLATFORM_NTX86);
  737. #endif
  738. b = SetupFindFirstLine (inf, DevSection, NULL, &isDev);
  739. if (!b) {
  740. wsprintf (AppendPos, TEXT(".%s"), INFSTR_PLATFORM_NT);
  741. b = SetupFindFirstLine (inf, DevSection, NULL, &isDev);
  742. if (!b) {
  743. *AppendPos = 0;
  744. b = SetupFindFirstLine (inf, DevSection, NULL, &isDev);
  745. }
  746. }
  747. UnsupportedDevice = FALSE;
  748. if (b) {
  749. if (SetupFindFirstLine (inf, DevSection, "DeviceUpgradeUnsupported", &isDev)) {
  750. if (SetupGetStringField (&isDev, 1, field, 12, NULL)) {
  751. if (_ttoi (field)) {
  752. UnsupportedDevice = TRUE;
  753. }
  754. }
  755. }
  756. } else {
  757. DEBUGMSG ((
  758. DBG_HWDB,
  759. "HwpAddPnpIdsInInf: no device section [%s] for [%s]",
  760. DevSection,
  761. Manufacturer
  762. ));
  763. }
  764. //
  765. // Get the device id
  766. //
  767. if (!SetupGetMultiSzField (&isMfg, 2, pnpId, 2048, NULL)) {
  768. DEBUGMSG ((
  769. DBG_HWDB,
  770. "HwpAddPnpIdsInInf: error retrieving PNPID field(s) in line %u in [%s]",
  771. isMfg.Line,
  772. Manufacturer
  773. ));
  774. continue;
  775. }
  776. //
  777. // Add each device id to the hash table
  778. //
  779. p = pnpId;
  780. while (*p) {
  781. BOOL b = TRUE;
  782. //
  783. // first invoke the callback (if specified)
  784. //
  785. if (Callback) {
  786. if (CallbackIsUnicode) {
  787. PWSTR uPnpid = ConvertToUnicodeSz (p);
  788. if (!uPnpid) {
  789. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  790. __leave;
  791. }
  792. if (!uInfPath) {
  793. uInfPath = ConvertToUnicodeSz (InfPath);
  794. }
  795. if (!uSourceDirectory) {
  796. uSourceDirectory = ConvertToUnicodeSz (SourceDirectory);
  797. }
  798. if (!uInfFilename) {
  799. uInfFilename = ConvertToUnicodeSz (InfFilename);
  800. }
  801. b = (*(HWDBAPPENDINFSCALLBACKW)Callback) (CallbackContext, uPnpid, uInfFilename, uSourceDirectory, uInfPath);
  802. FreeString (uPnpid);
  803. } else {
  804. b = (*Callback) (CallbackContext, p, InfFilename, SourceDirectory, InfPath);
  805. }
  806. }
  807. if (b) {
  808. //
  809. // First time through add the INF file name to string table
  810. //
  811. if (!infOffset) {
  812. if (Hwdb->InfFileTable) {
  813. fileName = _tcsrchr (InfPath, TEXT('\\')) + 1;
  814. infOffset = HtAddString (Hwdb->InfFileTable, fileName);
  815. if (!infOffset) {
  816. DEBUGMSG ((DBG_ERROR, "Cannot add %s to table of INFs.", fileName));
  817. __leave;
  818. }
  819. }
  820. }
  821. StringCopy (TrimmedPnpId, SkipSpace (p));
  822. TruncateTrailingSpace (TrimmedPnpId);
  823. result = HtAddStringEx (
  824. UnsupportedDevice ? Hwdb->UnsupPnpIdTable : Hwdb->PnpIdTable,
  825. TrimmedPnpId,
  826. (PVOID)&infOffset,
  827. CASE_INSENSITIVE
  828. );
  829. if (!result) {
  830. DEBUGMSG ((
  831. DBG_ERROR,
  832. "HwpAddPnpIdsInInf: cannot add %s to table of PNP IDs",
  833. TrimmedPnpId
  834. ));
  835. __leave;
  836. }
  837. }
  838. p = GetEndOfString (p) + 1;
  839. }
  840. } while (SetupFindNextLine (&isMfg, &isMfg));
  841. } while (SetupFindNextLine (&is, &is));
  842. } else {
  843. rc = GetLastError();
  844. //
  845. // If section not found, return success
  846. //
  847. if (rc == ERROR_SECTION_NOT_FOUND || rc == ERROR_LINE_NOT_FOUND) {
  848. SetLastError (ERROR_SUCCESS);
  849. DEBUGMSG ((
  850. DBG_HWDB,
  851. "HwpAddPnpIdsInInf: %s has no [Manufacturer] section or it's empty",
  852. InfPath
  853. ));
  854. } else {
  855. DEBUGMSG ((
  856. DBG_ERROR,
  857. "HwpAddPnpIdsInInf: error trying to find the [Manufacturer] section",
  858. InfPath
  859. ));
  860. __leave;
  861. }
  862. }
  863. Result = TRUE;
  864. }
  865. __finally {
  866. PushError();
  867. SetupCloseInfFile (inf);
  868. FreeString (uInfPath);
  869. FreeString (uSourceDirectory);
  870. FreeString (uInfFilename);
  871. PopError();
  872. DEBUGMSG ((DBG_HWDB, "HwpAddPnpIdsInInf: done parsing %s", InfPath));
  873. }
  874. return Result;
  875. }
  876. BOOL
  877. HwdbpAppendInfs (
  878. IN PHWDB Hwdb,
  879. IN PCSTR SourceDirectory,
  880. IN HWDBAPPENDINFSCALLBACKA Callback, OPTIONAL
  881. IN PVOID CallbackContext, OPTIONAL
  882. IN BOOL CallbackIsUnicode
  883. )
  884. {
  885. HANDLE h;
  886. WIN32_FIND_DATA fd;
  887. CHAR buffer[MAX_PATH];
  888. CHAR uncompressedFile[MAX_PATH];
  889. CHAR fullPath[MAX_PATH];
  890. DWORD rc;
  891. if (_sntprintf (buffer, MAX_PATH, "%s\\*.in?", SourceDirectory) < 0) {
  892. SetLastError (ERROR_INVALID_PARAMETER);
  893. DEBUGMSG ((
  894. DBG_ERROR,
  895. "HwdbpAppendInfs: file name too long: %s\\*.in?",
  896. SourceDirectory
  897. ));
  898. return FALSE;
  899. }
  900. h = FindFirstFile (buffer, &fd);
  901. if (h != INVALID_HANDLE_VALUE) {
  902. do {
  903. if (!HwpIsValidInfName (fd.cFileName, buffer, MAX_PATH)) {
  904. continue;
  905. }
  906. if (*buffer) {
  907. if (_snprintf (uncompressedFile, MAX_PATH, "%s\\%s", g_TempDir, buffer) < 0) {
  908. SetLastError (ERROR_INVALID_PARAMETER);
  909. DEBUGMSG ((
  910. DBG_ERROR,
  911. "HwdbpAppendInfs: file name too long: %s\\%s",
  912. g_TempDir,
  913. buffer
  914. ));
  915. continue;
  916. }
  917. if (_snprintf (fullPath, MAX_PATH, "%s\\%s", SourceDirectory, fd.cFileName) < 0) {
  918. SetLastError (ERROR_INVALID_PARAMETER);
  919. DEBUGMSG ((
  920. DBG_ERROR,
  921. "HwdbpAppendInfs: file name too long: %s\\%s",
  922. SourceDirectory,
  923. fd.cFileName
  924. ));
  925. continue;
  926. }
  927. SetFileAttributes (uncompressedFile, FILE_ATTRIBUTE_NORMAL);
  928. DeleteFile (uncompressedFile);
  929. rc = SetupDecompressOrCopyFile (fullPath, uncompressedFile, 0);
  930. if (rc != ERROR_SUCCESS) {
  931. LOG ((
  932. LOG_ERROR,
  933. "HwdbpAppendInfs: Could not decompress %s to %s",
  934. fullPath,
  935. uncompressedFile
  936. ));
  937. continue;
  938. } else {
  939. }
  940. } else {
  941. if (_snprintf (uncompressedFile, MAX_PATH, "%s\\%s", SourceDirectory, fd.cFileName) < 0) {
  942. SetLastError (ERROR_INVALID_PARAMETER);
  943. DEBUGMSG ((
  944. DBG_ERROR,
  945. "HwdbpAppendInfs: file name too long: %s\\%s",
  946. g_TempDir,
  947. buffer
  948. ));
  949. continue;
  950. }
  951. }
  952. if (!HwpAddPnpIdsInInf (
  953. uncompressedFile,
  954. Hwdb,
  955. SourceDirectory,
  956. *buffer ? buffer : fd.cFileName,
  957. Callback,
  958. CallbackContext,
  959. CallbackIsUnicode
  960. )) {
  961. DEBUGMSG ((
  962. DBG_ERROR,
  963. "HwdbpAppendInfs: HwpAddPnpIdsInInf(%s) failed",
  964. *buffer ? fullPath : uncompressedFile
  965. ));
  966. continue;
  967. }
  968. if (*buffer) {
  969. SetFileAttributes (uncompressedFile, FILE_ATTRIBUTE_NORMAL);
  970. DeleteFile (uncompressedFile);
  971. }
  972. } while (FindNextFile (h, &fd));
  973. FindClose (h);
  974. }
  975. return TRUE;
  976. }
  977. BOOL
  978. pAppendToHashTable (
  979. IN HASHTABLE HashTable,
  980. IN HASHITEM Index,
  981. IN PCSTR String,
  982. IN PVOID ExtraData,
  983. IN UINT ExtraDataSize,
  984. IN LPARAM lParam
  985. )
  986. {
  987. MYASSERT (lParam);
  988. return HtAddString ((HASHTABLE)lParam, String) != NULL;
  989. }
  990. BOOL
  991. HwdbpAppendDatabase (
  992. IN PHWDB HwdbTarget,
  993. IN PHWDB HwdbSource
  994. )
  995. {
  996. #if 0
  997. BOOL b = TRUE;
  998. if (HwdbSource->PnpIdTable) {
  999. if (!HwdbTarget->PnpIdTable) {
  1000. HwdbTarget->PnpIdTable = HtAllocWithData (sizeof (HASHITEM*));
  1001. if (!HwdbTarget->PnpIdTable) {
  1002. b = FALSE;
  1003. }
  1004. }
  1005. if (b) {
  1006. b = EnumHashTableWithCallback (
  1007. HwdbSource->PnpIdTable,
  1008. pAppendToHashTable,
  1009. HwdbTarget->PnpIdTable
  1010. );
  1011. }
  1012. }
  1013. if (b && HwdbSource->UnsupPnpIdTable) {
  1014. if (!HwdbTarget->UnsupPnpIdTable) {
  1015. HwdbTarget->UnsupPnpIdTable = HtAllocWithData (sizeof (HASHITEM*));
  1016. if (!HwdbTarget->UnsupPnpIdTable) {
  1017. b = FALSE;
  1018. }
  1019. }
  1020. if (b) {
  1021. b = EnumHashTableWithCallback (
  1022. HwdbSource->UnsupPnpIdTable,
  1023. pAppendToHashTable,
  1024. HwdbTarget->UnsupPnpIdTable
  1025. );
  1026. }
  1027. }
  1028. return b;
  1029. #endif
  1030. //
  1031. // not implemented
  1032. //
  1033. return FALSE;
  1034. }
  1035. BOOL
  1036. HwdbpHasDriver (
  1037. IN PHWDB Hwdb,
  1038. IN PCSTR PnpId,
  1039. OUT PBOOL Unsupported
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. HwdbpHasDriver determines if the PnpId is in the database
  1044. Arguments:
  1045. Hwdb - Specifies the database to search
  1046. PnpId - Specifies the PNPID to look for
  1047. Unsupported - Receives TRUE if the PNPID is unsupported
  1048. Return Value:
  1049. TRUE if the database has the PNPID
  1050. --*/
  1051. {
  1052. if (!Hwdb || !PnpId || !Unsupported) {
  1053. SetLastError (ERROR_INVALID_PARAMETER);
  1054. return FALSE;
  1055. }
  1056. //
  1057. // check if it's unsupported first
  1058. //
  1059. if (HtFindString (Hwdb->UnsupPnpIdTable, PnpId)) {
  1060. *Unsupported = TRUE;
  1061. return TRUE;
  1062. }
  1063. if (!HtFindString (Hwdb->PnpIdTable, PnpId)) {
  1064. return FALSE;
  1065. }
  1066. //
  1067. // fill out info
  1068. //
  1069. *Unsupported = FALSE;
  1070. return TRUE;
  1071. }
  1072. BOOL
  1073. HwdbpHasAnyDriver (
  1074. IN PHWDB Hwdb,
  1075. IN PCSTR PnpIds,
  1076. OUT PBOOL Unsupported
  1077. )
  1078. /*++
  1079. Routine Description:
  1080. HwdbpHasAnyDriver determines if any PNPID from the PnpIds multisz is in the database
  1081. Arguments:
  1082. Hwdb - Specifies the database to search
  1083. PnpIds - Specifies the list (multisz) of PNPIDs to look for
  1084. Unsupported - Receives TRUE if any PNPID in this list is unsupported
  1085. Return Value:
  1086. TRUE if the database has at least one of the PNPIDs in the list
  1087. --*/
  1088. {
  1089. BOOL bFound = FALSE;
  1090. PCSTR pnpID;
  1091. if (!Hwdb || !PnpIds || !Unsupported) {
  1092. SetLastError (ERROR_INVALID_PARAMETER);
  1093. return FALSE;
  1094. }
  1095. for (pnpID = PnpIds; *pnpID; pnpID = strchr (pnpID, 0) + 1) {
  1096. //
  1097. // check if it's unsupported first
  1098. //
  1099. if (HtFindString (Hwdb->UnsupPnpIdTable, pnpID)) {
  1100. *Unsupported = TRUE;
  1101. return TRUE;
  1102. }
  1103. if (HtFindString (Hwdb->PnpIdTable, pnpID)) {
  1104. bFound = TRUE;
  1105. }
  1106. }
  1107. //
  1108. // fill out info
  1109. //
  1110. *Unsupported = FALSE;
  1111. return bFound;
  1112. }
  1113. #if 0
  1114. typedef struct {
  1115. PHWDB Hwdb;
  1116. PHWDBENUM_CALLBACKA EnumCallback;
  1117. PVOID UserContext;
  1118. } HWDBENUM_DATAA, *PHWDBENUM_DATAA;
  1119. typedef struct {
  1120. PHWDB Hwdb;
  1121. PHWDBENUM_CALLBACKW EnumCallback;
  1122. PVOID UserContext;
  1123. } HWDBENUM_DATAW, *PHWDBENUM_DATAW;
  1124. BOOL
  1125. pCallbackEnumA (
  1126. IN HASHTABLE HashTable,
  1127. IN HASHITEM Index,
  1128. IN PCSTR PnpId,
  1129. IN PVOID ExtraData,
  1130. IN UINT ExtraDataSize,
  1131. IN LPARAM lParam
  1132. )
  1133. {
  1134. PHWDBENUM_DATAA ped = (PHWDBENUM_DATAA)lParam;
  1135. /*
  1136. PPNPID_DATA data = (PPNPID_DATA)ExtraData;
  1137. MYASSERT (ExtraDataSize == sizeof (PNPID_DATA);
  1138. return (*ped->EnumCallback) (
  1139. ped->UserContext,
  1140. PnpId,
  1141. pGetInfPath (ped->Hwdb, data->InfOffset),
  1142. data->Flags
  1143. );
  1144. */
  1145. return FALSE;
  1146. }
  1147. BOOL
  1148. HwdbpEnumeratePnpIdA (
  1149. IN PHWDB Hwdb,
  1150. IN PHWDBENUM_CALLBACKA EnumCallback,
  1151. IN PVOID UserContext
  1152. )
  1153. {
  1154. HWDBENUM_DATAA ed;
  1155. if (!Hwdb || !EnumCallback) {
  1156. SetLastError (ERROR_INVALID_PARAMETER);
  1157. return FALSE;
  1158. }
  1159. ed.Hwdb = Hwdb;
  1160. ed.EnumCallback = EnumCallback;
  1161. ed.UserContext = UserContext;
  1162. return EnumHashTableWithCallback (Hwdb->PnpIdTable, pCallbackEnumA, (LPARAM)&ed);
  1163. }
  1164. BOOL
  1165. pCallbackEnumW (
  1166. IN HASHTABLE HashTable,
  1167. IN HASHITEM Index,
  1168. IN PCSTR PnpId,
  1169. IN PVOID ExtraData,
  1170. IN UINT ExtraDataSize,
  1171. IN LPARAM lParam
  1172. )
  1173. {
  1174. PHWDBENUM_DATAW ped = (PHWDBENUM_DATAW)lParam;
  1175. /*
  1176. PPNPID_DATA data = (PPNPID_DATA)ExtraData;
  1177. MYASSERT (ExtraDataSize == sizeof (PNPID_DATA);
  1178. return (*ped->EnumCallback) (
  1179. ped->UserContext,
  1180. PnpId,
  1181. pGetInfPath (ped->Hwdb, data->InfOffset),
  1182. data->Flags
  1183. );
  1184. */
  1185. return FALSE;
  1186. }
  1187. BOOL
  1188. HwdbpEnumeratePnpIdW (
  1189. IN PHWDB Hwdb,
  1190. IN PHWDBENUM_CALLBACKW EnumCallback,
  1191. IN PVOID UserContext
  1192. )
  1193. {
  1194. HWDBENUM_DATAW ed;
  1195. if (!Hwdb || !EnumCallback) {
  1196. SetLastError (ERROR_INVALID_PARAMETER);
  1197. return FALSE;
  1198. }
  1199. ed.Hwdb = Hwdb;
  1200. ed.EnumCallback = EnumCallback;
  1201. ed.UserContext = UserContext;
  1202. return EnumHashTableWithCallback (Hwdb->PnpIdTable, pCallbackEnumW, (LPARAM)&ed);
  1203. }
  1204. #endif
  1205. BOOL
  1206. HwdbpEnumFirstInfA (
  1207. OUT PHWDBINF_ENUMA EnumPtr,
  1208. IN PCSTR DatabaseFile
  1209. )
  1210. {
  1211. CHAR buffer[MAX_PATH];
  1212. CHAR sig[sizeof (HWCOMPDAT_SIGNATURE)];
  1213. DWORD checksum;
  1214. DWORD rc;
  1215. DWORD BytesRead;
  1216. HASHITEM infOffset;
  1217. PHWDBINF_ENUM_INTERNAL pei;
  1218. if (!DatabaseFile || !EnumPtr) {
  1219. SetLastError (ERROR_INVALID_PARAMETER);
  1220. return FALSE;
  1221. }
  1222. if (!GetFullPathNameA (DatabaseFile, MAX_PATH, buffer, NULL)) {
  1223. return FALSE;
  1224. }
  1225. EnumPtr->Internal = (PHWDBINF_ENUM_INTERNAL) MemAlloc (g_hHeap, 0, sizeof (HWDBINF_ENUM_INTERNAL));
  1226. if (!EnumPtr->Internal) {
  1227. SetLastError (ERROR_OUTOFMEMORY);
  1228. return FALSE;
  1229. }
  1230. ZeroMemory (EnumPtr->Internal, sizeof (HWDBINF_ENUM_INTERNAL));
  1231. pei = (PHWDBINF_ENUM_INTERNAL)EnumPtr->Internal;
  1232. //
  1233. // Try to open the file
  1234. //
  1235. pei->File = CreateFileA (
  1236. buffer,
  1237. GENERIC_READ,
  1238. FILE_SHARE_READ, // share for read access
  1239. NULL, // no security attribs
  1240. OPEN_EXISTING,
  1241. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  1242. NULL // no template
  1243. );
  1244. if (pei->File == INVALID_HANDLE_VALUE) {
  1245. return FALSE;
  1246. }
  1247. //
  1248. // Look at the signature
  1249. //
  1250. ZeroMemory (sig, sizeof(sig));
  1251. if (!ReadFile (pei->File, sig, sizeof (HWCOMPDAT_SIGNATURE) - 1, &BytesRead, NULL) ||
  1252. lstrcmpA (HWCOMPDAT_SIGNATURE, sig)
  1253. ) {
  1254. SetLastError (ERROR_BAD_FORMAT);
  1255. goto exit;
  1256. }
  1257. //
  1258. // Get INF checksum
  1259. //
  1260. if (!pReadDword (pei->File, &checksum)) {
  1261. SetLastError (ERROR_BAD_FORMAT);
  1262. goto exit;
  1263. }
  1264. //
  1265. // Read in all PNP IDs
  1266. //
  1267. return HwdbpEnumNextInfA (EnumPtr);
  1268. exit:
  1269. HwdbpAbortEnumInfA (EnumPtr);
  1270. return FALSE;
  1271. }
  1272. BOOL
  1273. HwdbpEnumFirstInfW (
  1274. OUT PHWDBINF_ENUMW EnumPtr,
  1275. IN PCSTR DatabaseFile
  1276. )
  1277. {
  1278. HWDBINF_ENUMA ea;
  1279. if (!HwdbpEnumFirstInfA (&ea, DatabaseFile)) {
  1280. return FALSE;
  1281. }
  1282. EnumPtr->Internal = ea.Internal;
  1283. EnumPtr->InfFile = ConvertToUnicodeSz (ea.InfFile);
  1284. EnumPtr->PnpIds = ConvertToUnicodeMultiSz (ea.PnpIds);
  1285. if (EnumPtr->InfFile && EnumPtr->PnpIds) {
  1286. return TRUE;
  1287. }
  1288. HwdbpAbortEnumInfW (EnumPtr);
  1289. return FALSE;
  1290. }
  1291. BOOL
  1292. HwdbpEnumNextInfA (
  1293. IN OUT PHWDBINF_ENUMA EnumPtr
  1294. )
  1295. {
  1296. CHAR pnpId[1024];
  1297. PHWDBINF_ENUM_INTERNAL pei = (PHWDBINF_ENUM_INTERNAL)EnumPtr->Internal;
  1298. //
  1299. // Get next INF file name. If empty, we are done.
  1300. //
  1301. if (!pReadString (pei->File, EnumPtr->InfFile, sizeof (EnumPtr->InfFile))) {
  1302. SetLastError (ERROR_BAD_FORMAT);
  1303. goto exit;
  1304. }
  1305. if (EnumPtr->InfFile[0] == 0) {
  1306. SetLastError (ERROR_SUCCESS);
  1307. goto exit;
  1308. }
  1309. //
  1310. // Read in all PNP IDs for the INF
  1311. //
  1312. for (;;) {
  1313. //
  1314. // Get the PNP ID. If empty, we are done.
  1315. //
  1316. if (!pReadString (pei->File, pnpId, sizeof (pnpId))) {
  1317. SetLastError (ERROR_BAD_FORMAT);
  1318. goto exit;
  1319. }
  1320. if (*pnpId == 0) {
  1321. break;
  1322. }
  1323. if (!GbMultiSzAppendA (&pei->GrowBuf, pnpId)) {
  1324. SetLastError (ERROR_OUTOFMEMORY);
  1325. goto exit;
  1326. }
  1327. }
  1328. EnumPtr->PnpIds = (PCSTR)pei->GrowBuf.Buf;
  1329. return TRUE;
  1330. exit:
  1331. HwdbpAbortEnumInfA (EnumPtr);
  1332. return FALSE;
  1333. }
  1334. BOOL
  1335. HwdbpEnumNextInfW (
  1336. IN OUT PHWDBINF_ENUMW EnumPtr
  1337. )
  1338. {
  1339. HWDBINF_ENUMA ea;
  1340. ea.Internal = EnumPtr->Internal;
  1341. if (!HwdbpEnumNextInfA (&ea)) {
  1342. return FALSE;
  1343. }
  1344. EnumPtr->InfFile = ConvertToUnicodeSz (ea.InfFile);
  1345. EnumPtr->PnpIds = ConvertToUnicodeMultiSz (ea.PnpIds);
  1346. if (EnumPtr->InfFile && EnumPtr->PnpIds) {
  1347. return TRUE;
  1348. }
  1349. HwdbpAbortEnumInfW (EnumPtr);
  1350. return FALSE;
  1351. }
  1352. VOID
  1353. HwdbpAbortEnumInfA (
  1354. IN OUT PHWDBINF_ENUMA EnumPtr
  1355. )
  1356. {
  1357. PHWDBINF_ENUM_INTERNAL pei = (PHWDBINF_ENUM_INTERNAL)EnumPtr->Internal;
  1358. DWORD rc = GetLastError ();
  1359. if (pei) {
  1360. if (pei->File != INVALID_HANDLE_VALUE) {
  1361. CloseHandle (pei->File);
  1362. pei->File = INVALID_HANDLE_VALUE;
  1363. }
  1364. GbFree (&pei->GrowBuf);
  1365. }
  1366. SetLastError (rc);
  1367. }
  1368. VOID
  1369. HwdbpAbortEnumInfW (
  1370. IN OUT PHWDBINF_ENUMW EnumPtr
  1371. )
  1372. {
  1373. PHWDBINF_ENUM_INTERNAL pei = (PHWDBINF_ENUM_INTERNAL)EnumPtr->Internal;
  1374. DWORD rc = GetLastError ();
  1375. if (EnumPtr->InfFile) {
  1376. FreeString (EnumPtr->InfFile);
  1377. EnumPtr->InfFile = NULL;
  1378. }
  1379. if (EnumPtr->PnpIds) {
  1380. FreeString (EnumPtr->PnpIds);
  1381. EnumPtr->PnpIds = NULL;
  1382. }
  1383. if (pei) {
  1384. if (pei->File != INVALID_HANDLE_VALUE) {
  1385. CloseHandle (pei->File);
  1386. pei->File = INVALID_HANDLE_VALUE;
  1387. }
  1388. GbFree (&pei->GrowBuf);
  1389. }
  1390. SetLastError (rc);
  1391. }