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.

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