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.

4495 lines
121 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C S E T U P . C P P
  7. //
  8. // Contents: HRESULT wrappers for the Setup Api.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 16 Apr 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "ncsetup.h"
  18. #include "ncbase.h"
  19. #include "ncmem.h"
  20. #include "ncstring.h"
  21. #include "ncmisc.h"
  22. #include <swenum.h>
  23. extern const WCHAR c_szNo[];
  24. extern const WCHAR c_szYes[];
  25. // dwFieldIndex parameter for the first field. Fields indexes are 1 based
  26. // in Setup Api.
  27. //
  28. const DWORD c_dwFirstField = 1;
  29. //+---------------------------------------------------------------------------
  30. //
  31. // Function: HrSetupCommitFileQueue
  32. //
  33. // Purpose: Initializes the context used by the default queue callback
  34. // routine included with the Setup API in the same manner
  35. // as SetupInitDefaultQueueCallback, except that an
  36. // additional window is provided to the callback function
  37. // to accept progress messages.
  38. //
  39. // Arguments:
  40. // hwndOwner [in] See SetupApi for information
  41. // hfq [in]
  42. // pfc [in]
  43. // pvCtx [in]
  44. //
  45. // Returns: S_OK or a Win32 error code.
  46. //
  47. // Author: billbe 23 July 1997
  48. //
  49. // Notes:
  50. //
  51. HRESULT HrSetupCommitFileQueue(HWND hwndOwner, HSPFILEQ hfq,
  52. PSP_FILE_CALLBACK pfc, PVOID pvCtx)
  53. {
  54. Assert(hfq);
  55. Assert(INVALID_HANDLE_VALUE != hfq);
  56. Assert(pfc);
  57. Assert(pvCtx);
  58. HRESULT hr = S_OK;
  59. // Try to commit the queue
  60. if (!SetupCommitFileQueue(hwndOwner, hfq, pfc, pvCtx))
  61. {
  62. hr = HrFromLastWin32Error();
  63. }
  64. TraceError ("HrSetupCommitFileQueue", (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) ? S_OK : hr);
  65. return hr;
  66. }
  67. //+---------------------------------------------------------------------------
  68. //
  69. // Function: HrSetupInitDefaultQueueCallbackEx
  70. //
  71. // Purpose: Initializes the context used by the default queue callback
  72. // routine included with the Setup API in the same manner
  73. // as SetupInitDefaultQueueCallback, except that an
  74. // additional window is provided to the callback function
  75. // to accept progress messages.
  76. //
  77. // Arguments:
  78. // hwndOwner [in] See SetupApi for information
  79. // hwndAlternate [in]
  80. // uMsg [in]
  81. // dwReserved1 [in]
  82. // dwReserved2 [in]
  83. // ppvCtx [out]
  84. //
  85. // Returns: S_OK or a Win32 error code.
  86. //
  87. // Author: billbe 23 July 1997
  88. //
  89. // Notes:
  90. //
  91. HRESULT HrSetupInitDefaultQueueCallbackEx(HWND hwndOwner, HWND hwndAlternate,
  92. UINT uMsg, DWORD dwReserved1,
  93. PVOID pvReserved2, PVOID* ppvCtx)
  94. {
  95. Assert(ppvCtx);
  96. // Try to init default queue callback.
  97. //
  98. HRESULT hr;
  99. PVOID pvCtx = SetupInitDefaultQueueCallbackEx(hwndOwner, hwndAlternate,
  100. uMsg, dwReserved1, pvReserved2);
  101. if (pvCtx)
  102. {
  103. hr = S_OK;
  104. *ppvCtx = pvCtx;
  105. }
  106. else
  107. {
  108. hr = HrFromLastWin32Error ();
  109. *ppvCtx = NULL;
  110. }
  111. TraceError ("HrSetupInitDefaultQueueCallbackEx", hr);
  112. return hr;
  113. }
  114. //+---------------------------------------------------------------------------
  115. //
  116. // Function: HrSetupOpenFileQueue
  117. //
  118. // Purpose: Creates a setup file queue.
  119. //
  120. // Arguments:
  121. // phfq [out] See SetupApi for information
  122. //
  123. // Returns: S_OK or a Win32 error code.
  124. //
  125. // Author: billbe 23 July 1997
  126. //
  127. // Notes:
  128. //
  129. HRESULT HrSetupOpenFileQueue(HSPFILEQ* phfq)
  130. {
  131. Assert(phfq);
  132. // Try to open the file queue.
  133. //
  134. HRESULT hr;
  135. HSPFILEQ hfq = SetupOpenFileQueue();
  136. if (INVALID_HANDLE_VALUE != hfq)
  137. {
  138. hr = S_OK;
  139. *phfq = hfq;
  140. }
  141. else
  142. {
  143. hr = HrFromLastWin32Error ();
  144. *phfq = NULL;
  145. }
  146. TraceError ("HrSetupOpenFileQueue", hr);
  147. return hr;
  148. }
  149. //+---------------------------------------------------------------------------
  150. //
  151. // Function: HrSetupOpenInfFile
  152. //
  153. // Purpose: Open an INF file.
  154. //
  155. // Arguments:
  156. // pszFileName [in] See the Setup API documentation.
  157. // pszInfClass [in]
  158. // dwInfStyle [in]
  159. // punErrorLine [out]
  160. // phinf [out]
  161. //
  162. // Returns: S_OK or a Win32 error code.
  163. //
  164. // Author: shaunco 17 Apr 1997
  165. //
  166. // Notes:
  167. //
  168. HRESULT
  169. HrSetupOpenInfFile (
  170. PCWSTR pszFileName,
  171. PCWSTR pszInfClass,
  172. DWORD dwInfStyle,
  173. UINT* punErrorLine,
  174. HINF* phinf)
  175. {
  176. HRESULT hr;
  177. HINF hinf;
  178. Assert (pszFileName);
  179. Assert (phinf);
  180. // Try to open the file.
  181. //
  182. hinf = SetupOpenInfFile (pszFileName, pszInfClass,
  183. dwInfStyle, punErrorLine);
  184. if (INVALID_HANDLE_VALUE != hinf)
  185. {
  186. hr = S_OK;
  187. *phinf = hinf;
  188. }
  189. else
  190. {
  191. hr = HrFromLastWin32Error ();
  192. *phinf = NULL;
  193. if (punErrorLine)
  194. {
  195. *punErrorLine = 0;
  196. }
  197. }
  198. TraceHr (ttidError, FAL, hr, FALSE,
  199. "HrSetupOpenInfFile (%S)", pszFileName);
  200. return hr;
  201. }
  202. //+---------------------------------------------------------------------------
  203. //
  204. // Function: HrSetupFindFirstLine
  205. //
  206. // Purpose: Find the first line in an INF file with a matching section
  207. // and key.
  208. //
  209. // Arguments:
  210. // hinf [in] See the Setup API documentation.
  211. // pszSection [in]
  212. // pszKey [in]
  213. // pctx [out]
  214. //
  215. // Returns: S_OK or a Win32 error code.
  216. //
  217. // Author: shaunco 16 Apr 1997
  218. //
  219. // Notes:
  220. //
  221. HRESULT
  222. HrSetupFindFirstLine (
  223. IN HINF hinf,
  224. IN PCWSTR pszSection,
  225. IN PCWSTR pszKey,
  226. OUT INFCONTEXT* pctx)
  227. {
  228. Assert (hinf);
  229. Assert (pszSection);
  230. Assert (pctx);
  231. HRESULT hr;
  232. if (SetupFindFirstLine (hinf, pszSection, pszKey, pctx))
  233. {
  234. hr = S_OK;
  235. }
  236. else
  237. {
  238. hr = HrFromLastWin32Error ();
  239. }
  240. TraceErrorOptional ("HrSetupFindFirstLine", hr,
  241. (SPAPI_E_LINE_NOT_FOUND == hr));
  242. return hr;
  243. }
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Function: HrSetupFindNextLine
  247. //
  248. // Purpose: Find the next line in an INF file relative to ctxIn.
  249. //
  250. // Arguments:
  251. // ctxIn [in] See the Setup API documentation.
  252. // pctxOut [out]
  253. //
  254. // Returns: S_OK if successful, S_FALSE if there are no more lines, or a
  255. // Win32 error code.
  256. //
  257. // Author: shaunco 16 Apr 1997
  258. //
  259. // Notes:
  260. //
  261. HRESULT HrSetupFindNextLine (const INFCONTEXT& ctxIn, INFCONTEXT* pctxOut)
  262. {
  263. Assert (pctxOut);
  264. HRESULT hr;
  265. if (SetupFindNextLine (const_cast<PINFCONTEXT>(&ctxIn), pctxOut))
  266. {
  267. hr = S_OK;
  268. }
  269. else
  270. {
  271. hr = HrFromLastWin32Error ();
  272. if (SPAPI_E_LINE_NOT_FOUND == hr)
  273. {
  274. // Translate ERROR_LINE_NOT_FOUND into S_FALSE
  275. hr = S_FALSE;
  276. }
  277. }
  278. TraceError ("HrSetupFindNextLine", (hr == S_FALSE) ? S_OK : hr);
  279. return hr;
  280. }
  281. //+---------------------------------------------------------------------------
  282. //
  283. // Function: HrSetupFindNextMatchLine
  284. //
  285. // Purpose: Find the next line in an INF file relative to ctxIn and
  286. // matching an optional key.
  287. //
  288. // Arguments:
  289. // ctxIn [in] See the Setup API documentation.
  290. // pszKey [in]
  291. // pctxOut [out]
  292. //
  293. // Returns: S_OK or a Win32 error code.
  294. //
  295. // Author: shaunco 16 Apr 1997
  296. //
  297. // Notes:
  298. //
  299. HRESULT
  300. HrSetupFindNextMatchLine (
  301. IN const INFCONTEXT& ctxIn,
  302. IN PCWSTR pszKey,
  303. OUT INFCONTEXT* pctxOut)
  304. {
  305. Assert (pctxOut);
  306. HRESULT hr;
  307. if (SetupFindNextMatchLine ((PINFCONTEXT)&ctxIn, pszKey, pctxOut))
  308. {
  309. hr = S_OK;
  310. }
  311. else
  312. {
  313. hr = HrFromLastWin32Error();
  314. if (SPAPI_E_LINE_NOT_FOUND == hr)
  315. {
  316. // Translate ERROR_LINE_NOT_FOUND into S_FALSE
  317. hr = S_FALSE;
  318. }
  319. }
  320. TraceError ("HrSetupFindNextMatchLine", (hr == S_FALSE) ? S_OK : hr);
  321. return hr;
  322. }
  323. //+---------------------------------------------------------------------------
  324. //
  325. // Function: HrSetupGetLineByIndex
  326. //
  327. // Purpose: Locates a line in an INF file by its index value in the
  328. // specified section.
  329. //
  330. // Arguments:
  331. // hinf [in] See the Setup API documentation.
  332. // pszSection [in]
  333. // dwIndex [in]
  334. // pctx [out]
  335. //
  336. // Returns: S_OK or a Win32 error code.
  337. //
  338. // Author: shaunco 16 Apr 1997
  339. //
  340. // Notes:
  341. //
  342. HRESULT
  343. HrSetupGetLineByIndex (
  344. IN HINF hinf,
  345. IN PCWSTR pszSection,
  346. IN DWORD dwIndex,
  347. OUT INFCONTEXT* pctx)
  348. {
  349. Assert (pszSection);
  350. Assert (pctx);
  351. HRESULT hr;
  352. if (SetupGetLineByIndex (hinf, pszSection, dwIndex, pctx))
  353. {
  354. hr = S_OK;
  355. }
  356. else
  357. {
  358. hr = HrFromLastWin32Error ();
  359. }
  360. TraceError ("HrSetupGetLineByIndex", hr);
  361. return hr;
  362. }
  363. //+---------------------------------------------------------------------------
  364. //
  365. // Function: HrSetupGetLineCount
  366. //
  367. // Purpose: Get the number of lines in the specified section on an
  368. // INF file.
  369. //
  370. // Arguments:
  371. // hinf [in] See the Setup API documentation.
  372. // pszSection [in]
  373. // pulCount [out]
  374. //
  375. // Returns: S_OK or a Win32 error code.
  376. //
  377. // Author: shaunco 16 Apr 1997
  378. //
  379. // Notes:
  380. //
  381. HRESULT
  382. HrSetupGetLineCount (
  383. IN HINF hinf,
  384. IN PCWSTR pszSection,
  385. OUT ULONG* pulCount)
  386. {
  387. Assert (pszSection);
  388. Assert (pulCount);
  389. HRESULT hr;
  390. LONG lCount = SetupGetLineCount (hinf, pszSection);
  391. if (-1 != lCount)
  392. {
  393. *pulCount = lCount;
  394. hr = S_OK;
  395. }
  396. else
  397. {
  398. *pulCount = 0;
  399. hr = HrFromLastWin32Error ();
  400. }
  401. TraceError ("HrSetupGetLineCount", hr);
  402. return hr;
  403. }
  404. //+---------------------------------------------------------------------------
  405. //
  406. // Function: HrSetupGetBinaryField
  407. //
  408. // Purpose: Gets a binary value from an INF field.
  409. //
  410. // Arguments:
  411. // ctx [in] See the Setup API documentation.
  412. // dwFieldIndex [in]
  413. // pbBuf [out]
  414. // cbBuf [in]
  415. // pbRequired [out]
  416. //
  417. // Returns: S_OK or a Win32 error code.
  418. //
  419. // Author: shaunco 16 Apr 1997
  420. //
  421. // Notes:
  422. //
  423. HRESULT
  424. HrSetupGetBinaryField (
  425. IN const INFCONTEXT& ctx,
  426. IN DWORD dwFieldIndex,
  427. OUT BYTE* pbBuf,
  428. IN DWORD cbBuf,
  429. OUT DWORD* pbRequired)
  430. {
  431. HRESULT hr;
  432. if (SetupGetBinaryField ((PINFCONTEXT)&ctx, dwFieldIndex, pbBuf,
  433. cbBuf, pbRequired))
  434. {
  435. hr = S_OK;
  436. }
  437. else
  438. {
  439. hr = HrFromLastWin32Error ();
  440. if (pbBuf)
  441. {
  442. *pbBuf = 0;
  443. }
  444. if (pbRequired)
  445. {
  446. *pbRequired = 0;
  447. }
  448. }
  449. TraceError ("HrSetupGetBinaryField", hr);
  450. return hr;
  451. }
  452. //+---------------------------------------------------------------------------
  453. //
  454. // Function: HrSetupGetIntField
  455. //
  456. // Purpose: Gets an integer value from an INF field.
  457. //
  458. // Arguments:
  459. // ctx [in] See the Setup API documentation.
  460. // dwFieldIndex [in]
  461. // pnValue [out]
  462. //
  463. // Returns: S_OK or a Win32 error code.
  464. //
  465. // Author: shaunco 16 Apr 1997
  466. //
  467. // Notes:
  468. //
  469. HRESULT
  470. HrSetupGetIntField (
  471. IN const INFCONTEXT& ctx,
  472. IN DWORD dwFieldIndex,
  473. OUT INT* pnValue)
  474. {
  475. Assert (pnValue);
  476. HRESULT hr;
  477. if (SetupGetIntField (const_cast<PINFCONTEXT>(&ctx),
  478. dwFieldIndex, pnValue))
  479. {
  480. hr = S_OK;
  481. }
  482. else
  483. {
  484. hr = HrFromLastWin32Error ();
  485. *pnValue = 0;
  486. }
  487. TraceError ("HrSetupGetIntField", hr);
  488. return hr;
  489. }
  490. //+---------------------------------------------------------------------------
  491. //
  492. // Function: HrSetupGetMultiSzField
  493. //
  494. // Purpose: Gets a multi-sz value from an INF field.
  495. //
  496. // Arguments:
  497. // ctx [in] See the Setup API documentation.
  498. // dwFieldIndex [in]
  499. // pszBuf [out]
  500. // cchBuf [in]
  501. // pcchRequired [out]
  502. //
  503. // Returns: S_OK or a Win32 error code.
  504. //
  505. // Author: shaunco 16 Apr 1997
  506. //
  507. // Notes:
  508. //
  509. HRESULT
  510. HrSetupGetMultiSzField (
  511. const INFCONTEXT& ctx,
  512. DWORD dwFieldIndex,
  513. PWSTR pszBuf,
  514. DWORD cchBuf,
  515. DWORD* pcchRequired)
  516. {
  517. HRESULT hr;
  518. if (SetupGetMultiSzField (const_cast<PINFCONTEXT>(&ctx),
  519. dwFieldIndex, pszBuf, cchBuf, pcchRequired))
  520. {
  521. hr = S_OK;
  522. }
  523. else
  524. {
  525. hr = HrFromLastWin32Error ();
  526. if (pszBuf)
  527. {
  528. *pszBuf = 0;
  529. }
  530. if (pcchRequired)
  531. {
  532. *pcchRequired = 0;
  533. }
  534. }
  535. TraceError ("HrSetupGetMultiSzField", hr);
  536. return hr;
  537. }
  538. //+---------------------------------------------------------------------------
  539. //
  540. // Function: HrSetupGetMultiSzFieldWithAlloc
  541. //
  542. // Purpose: Gets a multi-sz value from an INF field. Allocates space for
  543. // it automatically.
  544. //
  545. // Arguments:
  546. // ctx [in] See the Setup API documentation.
  547. // dwFieldIndex [in]
  548. // ppszBuf [out]
  549. //
  550. // Returns: S_OK or a Win32 error code.
  551. //
  552. // Author: shaunco 16 Apr 1997
  553. //
  554. // Notes: Free the returned multi-sz with MemFree.
  555. //
  556. HRESULT HrSetupGetMultiSzFieldWithAlloc (
  557. const INFCONTEXT& ctx,
  558. DWORD dwFieldIndex,
  559. PWSTR* ppszBuf)
  560. {
  561. Assert (ppszBuf);
  562. // Initialize the output parameter.
  563. *ppszBuf = NULL;
  564. // First, get the size required.
  565. //
  566. HRESULT hr;
  567. DWORD cchRequired;
  568. hr = HrSetupGetMultiSzField (ctx, dwFieldIndex, NULL, 0, &cchRequired);
  569. if (S_OK == hr)
  570. {
  571. // Allocate the buffer.
  572. //
  573. PWSTR pszBuf = (PWSTR)MemAlloc(cchRequired * sizeof(WCHAR));
  574. if (pszBuf)
  575. {
  576. // Now fill the buffer.
  577. //
  578. hr = HrSetupGetMultiSzField (ctx, dwFieldIndex, pszBuf,
  579. cchRequired, NULL);
  580. if (S_OK == hr)
  581. {
  582. *ppszBuf = pszBuf;
  583. }
  584. else
  585. {
  586. MemFree (pszBuf);
  587. }
  588. }
  589. }
  590. TraceError ("HrSetupGetMultiSzFieldWithAlloc", hr);
  591. return hr;
  592. }
  593. //+---------------------------------------------------------------------------
  594. //
  595. // Function: HrSetupGetStringField
  596. //
  597. // Purpose: Gets a string from an INF field. Returns it as a tstring.
  598. //
  599. // Arguments:
  600. // ctx [in] See the Setup API documentation.
  601. // dwFieldIndex [in]
  602. // pstr [out]
  603. //
  604. // Returns: S_OK or a Win32 error code.
  605. //
  606. // Author: shaunco 16 Apr 1997
  607. //
  608. // Notes:
  609. //
  610. HRESULT HrSetupGetStringField (const INFCONTEXT& ctx,
  611. DWORD dwFieldIndex,
  612. tstring* pstr)
  613. {
  614. Assert (pstr);
  615. // First, get the size required.
  616. //
  617. DWORD cchRequired = 0;
  618. HRESULT hr = HrSetupGetStringField (ctx, dwFieldIndex, NULL, 0, &cchRequired);
  619. // 412390: workaround for bug in NT4 SETUPAPI.dll
  620. //
  621. if ((S_OK == hr) && (0 == cchRequired))
  622. {
  623. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  624. }
  625. if (S_OK == hr)
  626. {
  627. // Allocate a buffer on the stack.
  628. //
  629. PWSTR pszBuf;
  630. pszBuf = (PWSTR)PvAllocOnStack(cchRequired * sizeof(WCHAR));
  631. // Now fill the buffer.
  632. //
  633. hr = HrSetupGetStringField (ctx, dwFieldIndex, pszBuf, cchRequired, NULL);
  634. if (S_OK == hr)
  635. {
  636. *pstr = pszBuf;
  637. }
  638. }
  639. // If we failed for any reason, initialize the output parameter.
  640. //
  641. if (FAILED(hr))
  642. {
  643. pstr->erase ();
  644. }
  645. TraceError ("HrSetupGetStringField", hr);
  646. return hr;
  647. }
  648. //+---------------------------------------------------------------------------
  649. //
  650. // Function: HrSetupGetStringField
  651. //
  652. // Purpose: Gets a string from an INF field.
  653. //
  654. // Arguments:
  655. // ctx [in] See the Setup API documentation.
  656. // dwFieldIndex [in]
  657. // pszBuf [out]
  658. // cchBuf [in]
  659. // pcchRequired [out]
  660. //
  661. // Returns: S_OK or a Win32 error code.
  662. //
  663. // Author: shaunco 16 Apr 1997
  664. //
  665. // Notes:
  666. //
  667. HRESULT HrSetupGetStringField (
  668. IN const INFCONTEXT& ctx,
  669. IN DWORD dwFieldIndex,
  670. OUT PWSTR pszBuf,
  671. IN DWORD cchBuf,
  672. OUT DWORD* pcchRequired)
  673. {
  674. HRESULT hr;
  675. if (SetupGetStringField ((PINFCONTEXT)&ctx, dwFieldIndex, pszBuf,
  676. cchBuf, pcchRequired))
  677. {
  678. hr = S_OK;
  679. }
  680. else
  681. {
  682. hr = HrFromLastWin32Error ();
  683. if (pszBuf)
  684. {
  685. *pszBuf = 0;
  686. }
  687. if (pcchRequired)
  688. {
  689. *pcchRequired = 0;
  690. }
  691. }
  692. TraceError ("HrSetupGetStringField", hr);
  693. return hr;
  694. }
  695. //+---------------------------------------------------------------------------
  696. //
  697. // Function: HrSetupScanFileQueueWithNoCallback
  698. //
  699. // Purpose: Scans a setup file queue, performing an operation on each node
  700. // in its copy list. The operation is specified by a set of
  701. // flags. This function can be called either before or after
  702. // the queue has been committed.
  703. //
  704. // Arguments:
  705. // hfq [in] See SetupApi for information
  706. // dwFlags [in]
  707. // hwnd [in]
  708. // pdwResult [out]
  709. //
  710. // Returns: S_OK or a Win32 error code.
  711. //
  712. // Author: billbe 23 July 1997
  713. //
  714. // Notes: This differs from the SetupApi version in that no callback
  715. // can be specified through this wrapper. This is because
  716. // errors from the callback cannot not be reliably mapped
  717. // to an HRESULT. If a user defined callback is needed,
  718. // the original SetupApi function must be used.
  719. //
  720. HRESULT HrSetupScanFileQueueWithNoCallback(HSPFILEQ hfq, DWORD dwFlags,
  721. HWND hwnd, PDWORD pdwResult)
  722. {
  723. Assert(hfq);
  724. Assert(INVALID_HANDLE_VALUE != hfq);
  725. Assert(pdwResult);
  726. HRESULT hr = S_OK;
  727. // Scan the given queue
  728. if (!SetupScanFileQueue(hfq, dwFlags, hwnd, NULL, NULL, pdwResult))
  729. {
  730. hr = HrFromLastWin32Error();
  731. }
  732. TraceError ("HrSetupScanFileQueueWithNoCallback", hr);
  733. return hr;
  734. }
  735. //+---------------------------------------------------------------------------
  736. //
  737. // Function: HrSetupGetMultiSzFieldMapToDword
  738. //
  739. // Purpose: Gets the values represented as mult-sz in an INF
  740. // and returns the value as a DWORD of bit flags.
  741. // The mapping is specified by the caller through an array of
  742. // pointers to string values and their associated DWORD values.
  743. //
  744. // Example: The value in the INF might be "Ip,Ipx,Nbf".
  745. // This function can map these values to the DWORD
  746. // representation of FLAG_IP | FLAG_IPX | FLAG_NBF.
  747. //
  748. // Arguments:
  749. // ctx [in] See the Setup API documentation.
  750. // dwFieldIndex [in]
  751. // aMapSzDword [in] array of elements mapping a string to a DWORD.
  752. // cMapSzDword [in] count of elements in the array.
  753. // pdwValue [out] the returned value.
  754. //
  755. // Returns: S_OK or a Win32 error code.
  756. //
  757. // Author: shaunco 16 Apr 1997
  758. //
  759. // Notes: _wcsicmp is used to make the string comparisons.
  760. //
  761. HRESULT HrSetupGetMultiSzFieldMapToDword (const INFCONTEXT& ctx,
  762. DWORD dwFieldIndex,
  763. const MAP_SZ_DWORD* aMapSzDword,
  764. UINT cMapSzDword,
  765. DWORD* pdwValue)
  766. {
  767. Assert (aMapSzDword);
  768. Assert (cMapSzDword);
  769. Assert (pdwValue);
  770. // Initialize the output parameter.
  771. *pdwValue = 0;
  772. // Get the multi-sz value.
  773. //
  774. HRESULT hr;
  775. PWSTR pszBuf;
  776. hr = HrSetupGetMultiSzFieldWithAlloc (ctx, dwFieldIndex, &pszBuf);
  777. if (S_OK == hr)
  778. {
  779. DWORD dwValue = 0;
  780. // Map each value in the multi-sz to a DWORD and OR it into
  781. // the result.
  782. for (PCWSTR pszValue = pszBuf; *pszValue;
  783. pszValue += lstrlenW (pszValue) + 1)
  784. {
  785. // Search the map for a matching value. When found, update
  786. // dwValue.
  787. for (UINT i = 0; i < cMapSzDword; i++)
  788. {
  789. if (0 == lstrcmpiW (aMapSzDword[i].pszValue, pszValue))
  790. {
  791. dwValue |= aMapSzDword[i].dwValue;
  792. break;
  793. }
  794. }
  795. }
  796. // Assign the output parameter.
  797. *pdwValue = dwValue;
  798. MemFree (pszBuf);
  799. }
  800. TraceError ("HrSetupGetMultiSzFieldMapToDword", hr);
  801. return hr;
  802. }
  803. //+---------------------------------------------------------------------------
  804. //
  805. // Function: HrSetupGetStringFieldMapToDword
  806. //
  807. // Purpose: Gets a value represented as multiple strings in an INF
  808. // and returns it as a DWORD. The mapping is specified
  809. // by the caller through an array of pointers to string
  810. // values and their associated DWORD values.
  811. //
  812. // Example: Values in the INF might be "Yes" or "No".
  813. // This function can map these values to DWORD representations
  814. // of "1" and "0" respectively.
  815. //
  816. // Arguments:
  817. // ctx [in] See the Setup API documentation.
  818. // dwFieldIndex [in]
  819. // aMapSzDword [in] array of elements mapping a string to a DWORD.
  820. // cMapSzDword [in] count of elements in the array.
  821. // pdwValue [out] the returned value.
  822. //
  823. // Returns: S_OK if a match was found. If a match wasn't found,
  824. // HRESULT_FROM_WIN32(ERROR_INVALID_DATA) is returned.
  825. // Other Win32 error codes.
  826. //
  827. // Author: shaunco 16 Apr 1997
  828. //
  829. // Notes: lstrcmpiW is used to make the string comparisons.
  830. //
  831. HRESULT HrSetupGetStringFieldMapToDword (const INFCONTEXT& ctx,
  832. DWORD dwFieldIndex,
  833. const MAP_SZ_DWORD* aMapSzDword,
  834. UINT cMapSzDword,
  835. DWORD* pdwValue)
  836. {
  837. Assert (aMapSzDword);
  838. Assert (cMapSzDword);
  839. Assert (pdwValue);
  840. // Initialize the output parameter.
  841. *pdwValue = 0;
  842. // Get the string value.
  843. //
  844. tstring strValue;
  845. HRESULT hr = HrSetupGetStringField (ctx, dwFieldIndex, &strValue);
  846. if (SUCCEEDED(hr))
  847. {
  848. // Search the map for a matching value. When found, pass
  849. // the DWORD value out.
  850. // If the none of the strings matched, we'll return
  851. // an invalid data error code.
  852. hr = HRESULT_FROM_WIN32 (ERROR_INVALID_DATA);
  853. while (cMapSzDword--)
  854. {
  855. if (0 == lstrcmpiW (aMapSzDword->pszValue, strValue.c_str()))
  856. {
  857. *pdwValue = aMapSzDword->dwValue;
  858. hr = S_OK;
  859. break;
  860. }
  861. aMapSzDword++;
  862. }
  863. }
  864. TraceError ("HrSetupGetStringFieldMapToDword", hr);
  865. return hr;
  866. }
  867. //+---------------------------------------------------------------------------
  868. //
  869. // Function: HrSetupGetStringFieldAsBool
  870. //
  871. // Purpose: Gets the value of a boolean field represented as the
  872. // strings "Yes" and "No" in an INF file.
  873. //
  874. // Arguments:
  875. // ctx [in] See the Setup API documentation.
  876. // dwFieldIndex [in]
  877. // pfValue [out] the returned value.
  878. //
  879. // Returns: S_OK or a Win32 error code.
  880. //
  881. // Author: shaunco 16 Apr 1997
  882. //
  883. // Notes:
  884. //
  885. HRESULT HrSetupGetStringFieldAsBool (const INFCONTEXT& ctx,
  886. DWORD dwFieldIndex,
  887. BOOL* pfValue)
  888. {
  889. Assert (pfValue);
  890. // Initialize the output parameter.
  891. *pfValue = FALSE;
  892. static const MAP_SZ_DWORD aMapYesNo [] =
  893. {
  894. { c_szYes, TRUE },
  895. { c_szNo, FALSE },
  896. };
  897. DWORD dwValue;
  898. HRESULT hr = HrSetupGetStringFieldMapToDword (ctx, dwFieldIndex,
  899. aMapYesNo, celems(aMapYesNo),
  900. &dwValue);
  901. if (SUCCEEDED(hr))
  902. {
  903. *pfValue = !!dwValue;
  904. }
  905. TraceError ("HrSetupGetStringFieldAsBool", hr);
  906. return hr;
  907. }
  908. //+---------------------------------------------------------------------------
  909. //
  910. // Function: HrSetupGetFirstDword
  911. //
  912. // Purpose: Get a DWORD value from a section in the INF file.
  913. //
  914. // Arguments:
  915. // hinf [in] handle to an open INF file.
  916. // pszSection [in] specifies the section that contains the value.
  917. // pszKey [in] specifies the key that contains the value.
  918. // pdwValue [out] the returned value.
  919. //
  920. // Returns: S_OK or a Win32 error code.
  921. //
  922. // Author: shaunco 17 Apr 1997
  923. //
  924. // Notes:
  925. //
  926. HRESULT
  927. HrSetupGetFirstDword (
  928. IN HINF hinf,
  929. IN PCWSTR pszSection,
  930. IN PCWSTR pszKey,
  931. OUT DWORD* pdwValue)
  932. {
  933. Assert (pszSection);
  934. Assert (pszKey);
  935. // Initialize the output parameter.
  936. *pdwValue = 0;
  937. INFCONTEXT ctx;
  938. HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx);
  939. if (S_OK == hr)
  940. {
  941. INT nValue;
  942. hr = HrSetupGetIntField (ctx, c_dwFirstField, &nValue);
  943. if (S_OK == hr)
  944. {
  945. *pdwValue = nValue;
  946. }
  947. }
  948. TraceErrorOptional ("HrSetupGetFirstDword", hr,
  949. (SPAPI_E_LINE_NOT_FOUND == hr));
  950. return hr;
  951. }
  952. //+---------------------------------------------------------------------------
  953. //
  954. // Function: HrSetupGetFirstString
  955. //
  956. // Purpose: Get a string value from a section in the INF file.
  957. //
  958. // Arguments:
  959. // hinf [in] handle to an open INF file.
  960. // pszSection [in] specifies the section that contains the value.
  961. // pszKey [in] specifies the key that contains the value.
  962. // pdwValue [out] the returned value.
  963. //
  964. // Returns: S_OK or a Win32 error code.
  965. //
  966. // Author: shaunco 17 Apr 1997
  967. //
  968. // Notes:
  969. //
  970. HRESULT
  971. HrSetupGetFirstString (
  972. IN HINF hinf,
  973. IN PCWSTR pszSection,
  974. IN PCWSTR pszKey,
  975. OUT tstring* pstr)
  976. {
  977. Assert (pszSection);
  978. Assert (pszKey);
  979. INFCONTEXT ctx;
  980. HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx);
  981. if (S_OK == hr)
  982. {
  983. hr = HrSetupGetStringField (ctx, c_dwFirstField, pstr);
  984. }
  985. // If we failed for any reason, initialize the output parameter.
  986. //
  987. if (FAILED(hr))
  988. {
  989. pstr->erase ();
  990. }
  991. TraceErrorOptional ("HrSetupGetFirstString", hr,
  992. (SPAPI_E_SECTION_NOT_FOUND == hr) ||
  993. (SPAPI_E_LINE_NOT_FOUND == hr));
  994. return hr;
  995. }
  996. //+---------------------------------------------------------------------------
  997. //
  998. // Function: HrSetupGetFirstMultiSzFieldWithAlloc
  999. //
  1000. // Purpose: Retrieves the first occurrance of the given key in the given
  1001. // section of an INF file, allocates memory for it, and returns
  1002. // it in the parameter pszOut.
  1003. //
  1004. // Arguments:
  1005. // hinf [in] handle to an open INF file.
  1006. // pszSection [in] specifies the section that contains the value.
  1007. // pszKey [in] specifies the key that contains the value.
  1008. // pszOut [out] Returns multi-sz field.
  1009. //
  1010. // Returns: S_OK or a Win32 error code.
  1011. //
  1012. // Author: danielwe 7 May 1997
  1013. //
  1014. // Notes: Free the resulting string with MemFree.
  1015. //
  1016. HRESULT
  1017. HrSetupGetFirstMultiSzFieldWithAlloc (
  1018. IN HINF hinf,
  1019. IN PCWSTR pszSection,
  1020. IN PCWSTR pszKey,
  1021. OUT PWSTR* ppszOut)
  1022. {
  1023. Assert(pszSection);
  1024. Assert(pszKey);
  1025. Assert(ppszOut);
  1026. // Initialize the output parameter.
  1027. *ppszOut = 0;
  1028. INFCONTEXT ctx;
  1029. HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx);
  1030. if (S_OK == hr)
  1031. {
  1032. hr = HrSetupGetMultiSzFieldWithAlloc(ctx, c_dwFirstField, ppszOut);
  1033. }
  1034. TraceErrorOptional("HrSetupGetFirstMultiSzFieldWithAlloc", hr,
  1035. (SPAPI_E_LINE_NOT_FOUND == hr));
  1036. return hr;
  1037. }
  1038. //+---------------------------------------------------------------------------
  1039. //
  1040. // Function: HrSetupGetFirstMultiSzMapToDword
  1041. //
  1042. // Purpose: Get a DWORD value from a section in the INF file.
  1043. // The value is represented in the INF file as a multi-sz, but
  1044. // it is mapped to a DWORD value based on a caller-specified
  1045. // mapping. The string values in the map are compared using
  1046. // a case insensitive compare.
  1047. //
  1048. // Use this when the INF value can be one or more of a fixed
  1049. // set of values represented as strings.
  1050. //
  1051. // Example: [MySection] with a map of:
  1052. // MyKey = Ip,Nbf { "Ip", 0x01 }
  1053. // { "Ipx", 0x02 }
  1054. // { "Nbf", 0x04 }
  1055. //
  1056. // yields *pdwValue returned as 0x01 | 0x04 = 0x05.
  1057. //
  1058. // Arguments:
  1059. // hinf [in] handle to an open INF file.
  1060. // pszSection [in] specifies the section that contains the value.
  1061. // pszKey [in] specifies the key that contains the value.
  1062. // aMapSzDword [in] array of elements mapping a string to a DWORD.
  1063. // cMapSzDword [in] count of elements in the array.
  1064. // pdwValue [out] the returned value.
  1065. //
  1066. // Returns: S_OK or a Win32 error code.
  1067. //
  1068. // Author: shaunco 17 Apr 1997
  1069. //
  1070. // Notes: HrOpen must have been called before this call.
  1071. //
  1072. HRESULT
  1073. HrSetupGetFirstMultiSzMapToDword (
  1074. IN HINF hinf,
  1075. IN PCWSTR pszSection,
  1076. IN PCWSTR pszKey,
  1077. IN const MAP_SZ_DWORD* aMapSzDword,
  1078. IN UINT cMapSzDword,
  1079. OUT DWORD* pdwValue)
  1080. {
  1081. Assert (pszSection);
  1082. Assert (pszKey);
  1083. // Initialize the output parameter.
  1084. *pdwValue = 0;
  1085. INFCONTEXT ctx;
  1086. HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx);
  1087. if (S_OK == hr)
  1088. {
  1089. hr = HrSetupGetMultiSzFieldMapToDword (ctx, c_dwFirstField,
  1090. aMapSzDword, cMapSzDword,
  1091. pdwValue);
  1092. }
  1093. TraceErrorOptional ("HrSetupGetFirstMultiSzMapToDword", hr,
  1094. (SPAPI_E_LINE_NOT_FOUND == hr));
  1095. return hr;
  1096. }
  1097. //+---------------------------------------------------------------------------
  1098. //
  1099. // Member: HrSetupGetFirstStringMapToDword
  1100. //
  1101. // Purpose: Get a DWORD value from a section in the INF file.
  1102. // The value is represented in the INF file as a string, but
  1103. // it is mapped to a DWORD value based on a caller-specified
  1104. // mapping. The string values in the map are compared using
  1105. // a case insensitive compare.
  1106. //
  1107. // Use this when the INF value can be one of a fixed set of
  1108. // values represented as strings.
  1109. //
  1110. // Example: [MySection] with a map of:
  1111. // MyKey = ThisComputer { "Network", 1 }
  1112. // { "ThisComputer", 2 }
  1113. //
  1114. // yields *pdwValue returned as 2.
  1115. //
  1116. // Arguments:
  1117. // hinf [in] handle to an open INF file.
  1118. // pszSection [in] specifies the section that contains the value.
  1119. // pszKey [in] specifies the key that contains the value.
  1120. // aMapSzDword [in] array of elements mapping a string to a DWORD.
  1121. // cMapSzDword [in] count of elements in the array.
  1122. // pdwValue [out] the returned value.
  1123. //
  1124. // Returns: S_OK or a Win32 error code.
  1125. //
  1126. // Author: shaunco 17 Apr 1997
  1127. //
  1128. // Notes: HrOpen must have been called before this call.
  1129. //
  1130. HRESULT
  1131. HrSetupGetFirstStringMapToDword (
  1132. IN HINF hinf,
  1133. IN PCWSTR pszSection,
  1134. IN PCWSTR pszKey,
  1135. IN const MAP_SZ_DWORD* aMapSzDword,
  1136. IN UINT cMapSzDword,
  1137. OUT DWORD* pdwValue)
  1138. {
  1139. Assert (pszSection);
  1140. Assert (pszKey);
  1141. // Initialize the output parameter.
  1142. *pdwValue = 0;
  1143. INFCONTEXT ctx;
  1144. HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx);
  1145. if (S_OK == hr)
  1146. {
  1147. hr = HrSetupGetStringFieldMapToDword (ctx, c_dwFirstField,
  1148. aMapSzDword, cMapSzDword,
  1149. pdwValue);
  1150. }
  1151. TraceErrorOptional ("HrSetupGetFirstStringMapToDword", hr,
  1152. (SPAPI_E_LINE_NOT_FOUND == hr));
  1153. return hr;
  1154. }
  1155. //+---------------------------------------------------------------------------
  1156. //
  1157. // Function: HrSetupGetFirstStringAsBool
  1158. //
  1159. // Purpose: Get a boolean value from a section in the INF file.
  1160. // The boolean value is represented in the INF file as
  1161. // "Yes" or "No" (case insensitive) but the value is returned
  1162. // as a BOOL type.
  1163. //
  1164. // Example: [MySection]
  1165. // MyKey = yes
  1166. //
  1167. // yields *pfValue returned as TRUE.
  1168. //
  1169. // Arguments:
  1170. // hinf [in] handle to an open INF file.
  1171. // pszSection [in] specifies the section that contains the value.
  1172. // pszKey [in] specifies the key that contains the value.
  1173. // pdwValue [out] the returned value.
  1174. //
  1175. // Returns: S_OK or a Win32 error code.
  1176. //
  1177. // Author: shaunco 17 Apr 1997
  1178. //
  1179. // Notes:
  1180. //
  1181. HRESULT
  1182. HrSetupGetFirstStringAsBool (
  1183. IN HINF hinf,
  1184. IN PCWSTR pszSection,
  1185. IN PCWSTR pszKey,
  1186. OUT BOOL* pfValue)
  1187. {
  1188. Assert (hinf);
  1189. Assert (pszSection);
  1190. Assert (pszKey);
  1191. Assert (pfValue);
  1192. // Initialize the output parameter.
  1193. *pfValue = FALSE;
  1194. INFCONTEXT ctx;
  1195. HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx);
  1196. if (S_OK == hr)
  1197. {
  1198. hr = HrSetupGetStringFieldAsBool (ctx, c_dwFirstField, pfValue);
  1199. }
  1200. TraceErrorOptional ("HrSetupGetFirstStringAsBool", hr,
  1201. (SPAPI_E_LINE_NOT_FOUND == hr));
  1202. return hr;
  1203. }
  1204. //+---------------------------------------------------------------------------
  1205. //
  1206. // Function: HrSetupGetInfInformation
  1207. //
  1208. // Purpose: Returns the SP_INF_INFORMATION structure for the specified
  1209. // INF file to a caller-supplied buffer.
  1210. //
  1211. // Arguments:
  1212. // pvInfSpec [in] See SetupApi documentation for more info
  1213. // dwSearchControl [in]
  1214. // ppinfInfo [out]
  1215. //
  1216. // Returns: S_OK or a Win32 error code.
  1217. //
  1218. // Author: BillBe 18 Jan 1998
  1219. //
  1220. // Notes:
  1221. //
  1222. HRESULT
  1223. HrSetupGetInfInformation (
  1224. IN LPCVOID pvInfSpec,
  1225. IN DWORD dwSearchControl,
  1226. OUT PSP_INF_INFORMATION* ppinfInfo)
  1227. {
  1228. DWORD dwSize;
  1229. BOOL fSuccess;
  1230. *ppinfInfo = NULL;
  1231. if (fSuccess = SetupGetInfInformation (pvInfSpec, dwSearchControl,
  1232. NULL, 0, &dwSize))
  1233. {
  1234. *ppinfInfo = (PSP_INF_INFORMATION)MemAlloc (dwSize);
  1235. fSuccess = SetupGetInfInformation (pvInfSpec, dwSearchControl,
  1236. *ppinfInfo, dwSize, 0);
  1237. }
  1238. HRESULT hr = S_OK;
  1239. if (!fSuccess)
  1240. {
  1241. hr = HrFromLastWin32Error();
  1242. MemFree (*ppinfInfo);
  1243. *ppinfInfo = NULL;
  1244. }
  1245. TraceError("HrSetupGetInfInformation", hr);
  1246. return hr;
  1247. }
  1248. //+---------------------------------------------------------------------------
  1249. //
  1250. // Function: HrSetupIsValidNt5Inf
  1251. //
  1252. // Purpose: Determines if an inf file is a valid NT5 inf by examining
  1253. // its signature.
  1254. //
  1255. // Arguments:
  1256. // hinf [in] Handle to the inf file
  1257. //
  1258. // Returns: S_OK if valid, SPAPI_E_WRONG_INF_STYLE if invalid,
  1259. // or a Win32 error code.
  1260. //
  1261. // Author: BillBe 18 Jan 1998
  1262. //
  1263. // Notes: $WINDOWS 95$ is invalid and $CHICAGO$ is
  1264. // only valid if it has the required Compatible inf key in
  1265. // the version info.
  1266. //
  1267. HRESULT
  1268. HrSetupIsValidNt5Inf (
  1269. IN HINF hinf)
  1270. {
  1271. static const WCHAR c_szSignature[] = INFSTR_KEY_SIGNATURE;
  1272. static const WCHAR c_szCompatible[] = L"Compatible";
  1273. static const WCHAR c_szChicagoSig[] = L"$Chicago$";
  1274. static const WCHAR c_szWinntSig[] = L"$Windows NT$";
  1275. static const WCHAR c_szCompatibleValue[] = L"1";
  1276. PSP_INF_INFORMATION pinfInfo;
  1277. // Get the inf's version info
  1278. HRESULT hr = HrSetupGetInfInformation (hinf, INFINFO_INF_SPEC_IS_HINF,
  1279. &pinfInfo);
  1280. if (S_OK == hr)
  1281. {
  1282. PWSTR pszSignature;
  1283. // Get the signature info
  1284. hr = HrSetupQueryInfVersionInformation (pinfInfo, 0,
  1285. c_szSignature, &pszSignature);
  1286. if (S_OK == hr)
  1287. {
  1288. // if the inf signature is not windows nt...
  1289. if (0 != lstrcmpiW (pszSignature, c_szWinntSig))
  1290. {
  1291. // if it isn't Chicago, then we don't support it
  1292. if (0 != lstrcmpiW (pszSignature, c_szChicagoSig))
  1293. {
  1294. hr = SPAPI_E_WRONG_INF_STYLE;
  1295. }
  1296. else
  1297. {
  1298. // The signature is Chicago so now we check if
  1299. // the compatible line exists.
  1300. //
  1301. PWSTR pszCompatible;
  1302. hr = HrSetupQueryInfVersionInformation (pinfInfo, 0,
  1303. c_szCompatible, &pszCompatible);
  1304. if (S_OK == hr)
  1305. {
  1306. // We found the compatible line, now make sure
  1307. // it is set to c_szCompatibleValue.
  1308. //
  1309. if (0 != lstrcmpiW (pszCompatible, c_szCompatibleValue))
  1310. {
  1311. hr = SPAPI_E_WRONG_INF_STYLE;
  1312. }
  1313. MemFree (pszCompatible);
  1314. }
  1315. else if (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr)
  1316. {
  1317. // The Compatible key didn't exist so this is
  1318. // considered a windows 95 net inf
  1319. hr = SPAPI_E_WRONG_INF_STYLE;
  1320. }
  1321. }
  1322. }
  1323. MemFree (pszSignature);
  1324. }
  1325. MemFree (pinfInfo);
  1326. }
  1327. TraceError("HrSetupIsValidNt5Inf",
  1328. (SPAPI_E_WRONG_INF_STYLE == hr) ? S_OK : hr);
  1329. return hr;
  1330. }
  1331. //+---------------------------------------------------------------------------
  1332. //
  1333. // Function: HrSetupQueryInfVersionInformation
  1334. //
  1335. // Purpose: Returns INF file version information from an
  1336. // SP_INF_INFORMATION structure to a caller-supplied buffer.
  1337. //
  1338. //
  1339. //
  1340. // Arguments:
  1341. // pinfInfo [in] See SetupApi documentation for more info
  1342. // uiIndex [in]
  1343. // szKey [in]
  1344. // ppszInfo [out]
  1345. //
  1346. // Returns: S_OK or a Win32 error code.
  1347. //
  1348. // Author: BillBe 18 Jan 1998
  1349. //
  1350. // Notes:
  1351. //
  1352. HRESULT
  1353. HrSetupQueryInfVersionInformation (
  1354. IN PSP_INF_INFORMATION pinfInfo,
  1355. IN UINT uiIndex,
  1356. IN PCWSTR pszKey,
  1357. OUT PWSTR* ppszInfo)
  1358. {
  1359. Assert(pinfInfo);
  1360. *ppszInfo = NULL;
  1361. DWORD dwSize;
  1362. BOOL fSuccess = SetupQueryInfVersionInformation (pinfInfo, uiIndex,
  1363. pszKey, NULL, 0, &dwSize);
  1364. if (fSuccess)
  1365. {
  1366. *ppszInfo = (PWSTR)MemAlloc (dwSize * sizeof (WCHAR));
  1367. fSuccess = SetupQueryInfVersionInformation (pinfInfo, uiIndex, pszKey,
  1368. *ppszInfo, dwSize, NULL);
  1369. }
  1370. HRESULT hr = S_OK;
  1371. if (!fSuccess)
  1372. {
  1373. MemFree (*ppszInfo);
  1374. *ppszInfo = NULL;
  1375. hr = HrFromLastWin32Error();
  1376. }
  1377. TraceError("HrSetupQueryInfVersionInformation", hr);
  1378. return hr;
  1379. }
  1380. //+---------------------------------------------------------------------------
  1381. //
  1382. // Member: CSetupInfFile::Close
  1383. //
  1384. // Purpose: Close the INF file. It must have previously opened with
  1385. // a call to HrOpen().
  1386. //
  1387. // Arguments:
  1388. // (none)
  1389. //
  1390. // Returns: nothing
  1391. //
  1392. // Author: shaunco 16 Apr 1997
  1393. //
  1394. // Notes:
  1395. //
  1396. void CSetupInfFile::Close ()
  1397. {
  1398. AssertSz (m_hinf, "You shouldn't be closing a file that is already closed.");
  1399. ::SetupCloseInfFile (m_hinf);
  1400. m_hinf = NULL;
  1401. }
  1402. //+---------------------------------------------------------------------------
  1403. //
  1404. // Member: CSetupInfFile::EnsureClosed
  1405. //
  1406. // Purpose: Ensure the INF file represented by this object is closed.
  1407. //
  1408. // Arguments:
  1409. // (none)
  1410. //
  1411. // Returns: nothing
  1412. //
  1413. // Author: shaunco 16 Apr 1997
  1414. //
  1415. // Notes:
  1416. //
  1417. void CSetupInfFile::EnsureClosed()
  1418. {
  1419. if (m_hinf)
  1420. {
  1421. Close ();
  1422. }
  1423. }
  1424. //+--------------------------------------------------------------------------
  1425. //
  1426. // Function: HrSetupDiCallClassInstaller
  1427. //
  1428. // Purpose: calls the appropriate class installer with the specified
  1429. // installation request (DI_FUNCTION).
  1430. //
  1431. // Arguments:
  1432. // dif [in] See SetupApi for more info
  1433. // hdi [in] See SetupApi for more info
  1434. // pdeid [in] See SetupApi for more info
  1435. //
  1436. // Returns: HRESULT. S_OK if successful, error code otherwise
  1437. //
  1438. // Author: billbe 25 June 1997
  1439. //
  1440. // Notes: SPAPI_E_DI_DO_DEFAULT is mapped to S_OK
  1441. //
  1442. HRESULT
  1443. HrSetupDiCallClassInstaller(
  1444. IN DI_FUNCTION dif,
  1445. IN HDEVINFO hdi,
  1446. IN PSP_DEVINFO_DATA pdeid)
  1447. {
  1448. Assert(INVALID_HANDLE_VALUE != hdi);
  1449. Assert(hdi);
  1450. HRESULT hr = S_OK;
  1451. // Call the class installer and convert any errors
  1452. if (!SetupDiCallClassInstaller(dif, hdi, pdeid))
  1453. {
  1454. hr = HrFromLastWin32Error();
  1455. if (SPAPI_E_DI_DO_DEFAULT == hr)
  1456. {
  1457. hr = S_OK;
  1458. }
  1459. }
  1460. TraceError("HrSetupDiCallClassInstaller",
  1461. (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) ? S_OK : hr);
  1462. return hr;
  1463. }
  1464. //+--------------------------------------------------------------------------
  1465. //
  1466. // Function: HrSetupCopyOEMInf
  1467. //
  1468. // Purpose: HRESULT wrapper for SetupCopyOEMInf that returns the
  1469. // new file path and name as tstrings
  1470. //
  1471. // Arguments:
  1472. // szSourceName [in] See SetupApi for more info
  1473. // szSourceMediaLocation [in]
  1474. // dwSourceMediaType [in]
  1475. // dwCopyStyle [in]
  1476. // pstrDestFilename [out]
  1477. // pstrDestFilenameComponent [out]
  1478. //
  1479. // Returns: HRESULT. S_OK if successful, or Win32 converted error code
  1480. //
  1481. // Author: billbe 15 May 1997
  1482. //
  1483. // Notes: See SetupCopyOEMInf in SetupApi for more info
  1484. //
  1485. HRESULT
  1486. HrSetupCopyOemInf(
  1487. IN const tstring& strSourceName,
  1488. IN const tstring& strSourceMediaLocation, OPTIONAL
  1489. IN DWORD dwSourceMediaType,
  1490. IN DWORD dwCopyStyle,
  1491. OUT tstring* pstrDestFilename, OPTIONAL
  1492. OUT tstring* pstrDestFilenameComponent OPTIONAL)
  1493. {
  1494. Assert(!strSourceName.empty());
  1495. BOOL fWin32Success = TRUE;
  1496. DWORD cchRequiredSize;
  1497. // Copy the file and get the size for the new filename in case it is
  1498. // needed
  1499. if (fWin32Success = SetupCopyOEMInf(strSourceName.c_str(),
  1500. strSourceMediaLocation.c_str(), dwSourceMediaType, dwCopyStyle,
  1501. NULL, NULL, &cchRequiredSize, NULL))
  1502. {
  1503. // If any of the out parameters are specified, we need to get the
  1504. // information
  1505. if (pstrDestFilename || pstrDestFilenameComponent)
  1506. {
  1507. PWSTR pszDestPath = NULL;
  1508. PWSTR pszDestFilename = NULL;
  1509. // now we allocate space to get the destination file path.
  1510. // We allocate on the stack for automatic clean-up
  1511. // Note: dwRequiredSize includes the terminating NULL
  1512. //
  1513. pszDestPath = (PWSTR)_alloca(cchRequiredSize * sizeof(WCHAR));
  1514. // Get the new file path and filename
  1515. if (fWin32Success = SetupCopyOEMInf(strSourceName.c_str(),
  1516. strSourceMediaLocation.c_str(), dwSourceMediaType,
  1517. dwCopyStyle, pszDestPath, cchRequiredSize, NULL,
  1518. &pszDestFilename))
  1519. {
  1520. // if the file path is needed, assign it
  1521. if (pstrDestFilename)
  1522. {
  1523. *pstrDestFilename = pszDestPath;
  1524. }
  1525. // If the user wants just the filename, assign it to the
  1526. // string
  1527. if (pstrDestFilenameComponent)
  1528. {
  1529. *pstrDestFilenameComponent = pszDestFilename;
  1530. }
  1531. }
  1532. else
  1533. {
  1534. // initialize out params on failure
  1535. //
  1536. if (pstrDestFilename)
  1537. {
  1538. pstrDestFilename->erase();
  1539. }
  1540. if (pstrDestFilenameComponent)
  1541. {
  1542. pstrDestFilenameComponent->erase();
  1543. }
  1544. }
  1545. }
  1546. }
  1547. HRESULT hr = S_OK;
  1548. if (!fWin32Success)
  1549. {
  1550. hr = HrFromLastWin32Error();
  1551. }
  1552. TraceError("HrSetupCopyOEMInf", hr);
  1553. return hr;
  1554. }
  1555. //+--------------------------------------------------------------------------
  1556. //
  1557. // Function: HrSetupCopyOEMInf
  1558. //
  1559. // Purpose: HRESULT wrapper for SetupCopyOEMInf that returns the
  1560. // new file path and name as tstrings
  1561. //
  1562. // Arguments:
  1563. // pszSourceName [in] See SetupApi for more info
  1564. // pszSourceMediaLocation [in]
  1565. // dwSourceMediaType [in]
  1566. // dwCopyStyle [in]
  1567. // pszDestFilename [out] // must be at least _MAX_PATH chars.
  1568. // ppszDestFilenameComponent [out]
  1569. //
  1570. // Returns: HRESULT. S_OK if successful, or Win32 converted error code
  1571. //
  1572. // Author: billbe 15 May 1997
  1573. //
  1574. // Notes: See SetupCopyOEMInf in SetupApi for more info
  1575. //
  1576. HRESULT
  1577. HrSetupCopyOemInfBuffer(
  1578. IN PCWSTR pszSourceName,
  1579. IN PCWSTR pszSourceMediaLocation, OPTIONAL
  1580. IN DWORD SourceMediaType,
  1581. IN DWORD CopyStyle,
  1582. OUT PWSTR pszDestFilename,
  1583. IN DWORD cchDestFilename,
  1584. OUT PWSTR* ppszDestFilenameComponent OPTIONAL)
  1585. {
  1586. Assert(pszSourceName);
  1587. Assert(pszDestFilename);
  1588. BOOL fWin32Success = TRUE;
  1589. if (!(fWin32Success = SetupCopyOEMInf(pszSourceName,
  1590. pszSourceMediaLocation, SourceMediaType,
  1591. CopyStyle, pszDestFilename, cchDestFilename, NULL,
  1592. ppszDestFilenameComponent)))
  1593. {
  1594. // initialize out params on failure
  1595. //
  1596. *pszDestFilename = 0;
  1597. if (*ppszDestFilenameComponent)
  1598. {
  1599. *ppszDestFilenameComponent = NULL;
  1600. }
  1601. }
  1602. HRESULT hr = S_OK;
  1603. if (!fWin32Success)
  1604. {
  1605. hr = HrFromLastWin32Error();
  1606. }
  1607. TraceHr (ttidError, FAL, hr, FALSE, "HrSetupCopyOEMInf");
  1608. return hr;
  1609. }
  1610. //+--------------------------------------------------------------------------
  1611. //
  1612. // Function: HrSetupDiBuildDriverInfoList
  1613. //
  1614. // Purpose: builds a list of drivers associated with a specified device
  1615. // instance or with the device information set's global
  1616. // class driver list.
  1617. //
  1618. // Arguments:
  1619. // hdi [in] See SetupApi for more info
  1620. // pdeid [in, out]
  1621. // dwDriverType [in]
  1622. //
  1623. // Returns: HRESULT. S_OK if successful, error code otherwise
  1624. //
  1625. // Author: billbe 26 June 1997
  1626. //
  1627. // Notes:
  1628. //
  1629. HRESULT
  1630. HrSetupDiBuildDriverInfoList(IN HDEVINFO hdi, IN OUT PSP_DEVINFO_DATA pdeid,
  1631. IN DWORD dwDriverType)
  1632. {
  1633. Assert(IsValidHandle(hdi));
  1634. HRESULT hr = S_OK;
  1635. // Build the list
  1636. if (!SetupDiBuildDriverInfoList(hdi, pdeid, dwDriverType))
  1637. {
  1638. hr = HrFromLastWin32Error();
  1639. }
  1640. TraceError("HrSetupDiBuildDriverInfoList", hr);
  1641. return hr;
  1642. }
  1643. //+--------------------------------------------------------------------------
  1644. //
  1645. // Function: HrSetupDiCreateDeviceInfo
  1646. //
  1647. // Purpose: creates a new device information element and adds it as a
  1648. // new member to the specified device information set.
  1649. //
  1650. // Arguments:
  1651. // hdi [in] See SetupApi for more info
  1652. // pszDeviceName [in] See SetupApi for more info
  1653. // guidClass [in] See SetupApi for more info
  1654. // pszDesc [in] See SetupApi for more info
  1655. // hwndParent [in] See SetupApi for more info
  1656. // dwFlags [in] See SetupApi for more info
  1657. // pdeid [out] See SetupApi for more info
  1658. //
  1659. // Returns: HRESULT. S_OK if successful, error code otherwise
  1660. //
  1661. // Author: billbe 26 June 1997
  1662. //
  1663. // Notes: pdeid is initialized and its cbSize field set by this fcn
  1664. //
  1665. HRESULT
  1666. HrSetupDiCreateDeviceInfo(
  1667. IN HDEVINFO hdi,
  1668. IN PCWSTR pszDeviceName,
  1669. IN const GUID& guidClass,
  1670. IN PCWSTR pszDesc, OPTIONAL
  1671. IN HWND hwndParent, OPTIONAL
  1672. IN DWORD dwFlags,
  1673. OUT PSP_DEVINFO_DATA pdeid OPTIONAL)
  1674. {
  1675. Assert(IsValidHandle(hdi));
  1676. Assert(pszDeviceName);
  1677. if (pdeid)
  1678. {
  1679. ZeroMemory(pdeid, sizeof(SP_DEVINFO_DATA));
  1680. pdeid->cbSize = sizeof(SP_DEVINFO_DATA);
  1681. }
  1682. HRESULT hr = S_OK;
  1683. // Create the device info node
  1684. if (!SetupDiCreateDeviceInfo (hdi, pszDeviceName, &guidClass, pszDesc,
  1685. hwndParent, dwFlags, pdeid))
  1686. {
  1687. hr = HrFromLastWin32Error();
  1688. }
  1689. TraceError ("HrSetupDiCreateDeviceInfo", hr);
  1690. return hr;
  1691. }
  1692. //+--------------------------------------------------------------------------
  1693. //
  1694. // Function: HrSetupDiEnumDeviceInfo
  1695. //
  1696. // Purpose: Enumerates the members of the specified device information
  1697. // set.
  1698. //
  1699. // Arguments:
  1700. // hdi [in] See SetupApi for more info
  1701. // dwIndex [in] See SetupApi for more info
  1702. // pdeid [in] See SetupApi for more info
  1703. //
  1704. // Returns: HRESULT. S_OK if successful, error code otherwise
  1705. //
  1706. // Author: billbe 13 June 1997
  1707. //
  1708. // Notes:
  1709. //
  1710. HRESULT
  1711. HrSetupDiEnumDeviceInfo(
  1712. IN HDEVINFO hdi,
  1713. IN DWORD dwIndex,
  1714. OUT PSP_DEVINFO_DATA pdeid)
  1715. {
  1716. Assert(IsValidHandle(hdi));
  1717. Assert(pdeid);
  1718. HRESULT hr;
  1719. ZeroMemory(pdeid, sizeof(SP_DEVINFO_DATA));
  1720. pdeid->cbSize = sizeof(SP_DEVINFO_DATA);
  1721. if (SetupDiEnumDeviceInfo (hdi, dwIndex, pdeid))
  1722. {
  1723. hr = S_OK;
  1724. }
  1725. else
  1726. {
  1727. hr = HrFromLastWin32Error();
  1728. }
  1729. TraceErrorOptional("HrSetupDiEnumDeviceInfo", hr,
  1730. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr);
  1731. return hr;
  1732. }
  1733. //+--------------------------------------------------------------------------
  1734. //
  1735. // Function: HrSetupDiEnumDriverInfo
  1736. //
  1737. // Purpose: Enumerates the members of a driver information list.
  1738. //
  1739. // Arguments:
  1740. // hdi [in] See SetupApi for more info
  1741. // pdeid [in]
  1742. // dwDriverType [in]
  1743. // dwIndex [in]
  1744. // pdrid [out]
  1745. //
  1746. // Returns: HRESULT. S_OK if successful, error code otherwise
  1747. //
  1748. // Author: billbe 26 June 1997
  1749. //
  1750. // Notes:
  1751. //
  1752. HRESULT
  1753. HrSetupDiEnumDriverInfo(
  1754. IN HDEVINFO hdi,
  1755. IN PSP_DEVINFO_DATA pdeid,
  1756. IN DWORD dwDriverType,
  1757. IN DWORD dwIndex,
  1758. OUT PSP_DRVINFO_DATA pdrid)
  1759. {
  1760. Assert(IsValidHandle(hdi));
  1761. Assert(pdrid);
  1762. HRESULT hr = S_OK;
  1763. // initialize the out param
  1764. ZeroMemory(pdrid, sizeof(SP_DRVINFO_DATA));
  1765. pdrid->cbSize = sizeof(SP_DRVINFO_DATA);
  1766. // call the enum fcn
  1767. if (!SetupDiEnumDriverInfo(hdi, pdeid, dwDriverType, dwIndex, pdrid))
  1768. {
  1769. hr = HrFromLastWin32Error();
  1770. }
  1771. TraceErrorOptional("HrSetupDiEnumDriverInfo", hr,
  1772. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr);
  1773. return hr;
  1774. }
  1775. //+--------------------------------------------------------------------------
  1776. //
  1777. // Function: HrSetupDiSelectBestCompatDrv
  1778. //
  1779. // Purpose: Finds and selects the best driver for the current device.
  1780. //
  1781. // Arguments:
  1782. // hdi [in] See SetupApi for more info
  1783. // pdeid [in][out]
  1784. //
  1785. // Returns: HRESULT. S_OK if successful, error code otherwise
  1786. //
  1787. // Author: billbe 26 June 1997
  1788. //
  1789. // Notes:
  1790. //
  1791. HRESULT
  1792. HrSetupDiSelectBestCompatDrv(
  1793. IN HDEVINFO hdi,
  1794. IN OUT PSP_DEVINFO_DATA pdeid)
  1795. {
  1796. Assert(IsValidHandle(hdi));
  1797. Assert(pdeid);
  1798. HRESULT hr = S_OK;
  1799. // call the SelectBestCompatDrv fcn
  1800. if (!SetupDiSelectBestCompatDrv(hdi, pdeid))
  1801. {
  1802. hr = HrFromLastWin32Error();
  1803. }
  1804. TraceErrorOptional("HrSetupDiSelectBestCompatDrv", hr,
  1805. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr);
  1806. return hr;
  1807. }
  1808. //+--------------------------------------------------------------------------
  1809. //
  1810. // Function: HrSetupDiGetDeviceInfoListClass
  1811. //
  1812. // Purpose: Retrieves the class GUID associated with a device
  1813. // information set if it has an associated class.
  1814. //
  1815. // Arguments:
  1816. // hdi [in] See SetupApi for more info
  1817. // pguid [out]
  1818. //
  1819. // Returns: HRESULT. S_OK if successful, error code otherwise
  1820. //
  1821. // Author: billbe 26 June 1997
  1822. //
  1823. // Notes:
  1824. //
  1825. HRESULT
  1826. HrSetupDiGetDeviceInfoListClass (
  1827. IN HDEVINFO hdi,
  1828. OUT GUID* pguid)
  1829. {
  1830. Assert(IsValidHandle(hdi));
  1831. Assert(pguid);
  1832. HRESULT hr = S_OK;
  1833. // Get the guid for the HDEVINFO
  1834. if (!SetupDiGetDeviceInfoListClass (hdi, pguid))
  1835. {
  1836. hr = HrFromLastWin32Error();
  1837. }
  1838. TraceError("HrSetupDiGetDeviceInfoListClass", hr);
  1839. return hr;
  1840. }
  1841. //+--------------------------------------------------------------------------
  1842. //
  1843. // Function: HrSetupDiGetClassDevs
  1844. //
  1845. // Purpose: Returns a device information set that contains all installed
  1846. // devices of a specified class.
  1847. //
  1848. // Arguments:
  1849. // pguidClass [in] See SetupApi for more info
  1850. // pszEnumerator [in] See SetupApi for more info
  1851. // hwndParent [in] See SetupApi for more info
  1852. // dwFlags [in] See SetupApi for more info
  1853. // phdi [out] See SetupApi for more info
  1854. //
  1855. // Returns: HRESULT. S_OK if successful, error code otherwise
  1856. //
  1857. // Author: billbe 13 June 1997
  1858. //
  1859. // Notes:
  1860. //
  1861. HRESULT
  1862. HrSetupDiGetClassDevs (
  1863. IN const GUID* pguidClass, OPTIONAL
  1864. IN PCWSTR pszEnumerator, OPTIONAL
  1865. IN HWND hwndParent, OPTIONAL
  1866. IN DWORD dwFlags,
  1867. OUT HDEVINFO* phdi)
  1868. {
  1869. Assert(phdi);
  1870. HRESULT hr;
  1871. HDEVINFO hdi = SetupDiGetClassDevsW (pguidClass, pszEnumerator,
  1872. hwndParent, dwFlags);
  1873. if (INVALID_HANDLE_VALUE != hdi)
  1874. {
  1875. hr = S_OK;
  1876. *phdi = hdi;
  1877. }
  1878. else
  1879. {
  1880. hr = HrFromLastWin32Error();
  1881. *phdi = NULL;
  1882. }
  1883. TraceError ("HrSetupDiGetClassDevs", hr);
  1884. return hr;
  1885. }
  1886. //+--------------------------------------------------------------------------
  1887. //
  1888. // Function: HrSetupDiGetDeviceInstanceId
  1889. //
  1890. // Purpose: HRESULT wrapper for SetupDiGetDeviceInstanceId.
  1891. //
  1892. // Arguments:
  1893. // hdi [in] See SetupApi for more info.
  1894. // pdeid [in] See SetupApi for more info.
  1895. // pszId [out] The device instance Id for the net card.
  1896. // cchId [in] The size of pszId in characters.
  1897. // pcchRequired [out] Optional. The required buffer size in characters.
  1898. //
  1899. //
  1900. // Returns: HRESULT. S_OK if successful, error code otherwise.
  1901. //
  1902. // Author: billbe 26 Mar 1997
  1903. //
  1904. // Notes: See SetupDiGetDeviceInstanceId in Device Installer for more info.
  1905. //
  1906. HRESULT
  1907. HrSetupDiGetDeviceInstanceId(
  1908. IN HDEVINFO hdi,
  1909. IN PSP_DEVINFO_DATA pdeid,
  1910. OUT PWSTR pszId,
  1911. IN DWORD cchId,
  1912. OUT OPTIONAL DWORD* pcchRequired)
  1913. {
  1914. Assert(IsValidHandle(hdi));
  1915. Assert(pdeid);
  1916. DWORD cchRequiredSize;
  1917. BOOL fSuccess = TRUE;
  1918. HRESULT hr = S_OK;
  1919. // Get the buffer length required for the instance Id.
  1920. if (!(fSuccess = SetupDiGetDeviceInstanceIdW(hdi, pdeid, NULL, 0,
  1921. &cchRequiredSize)))
  1922. {
  1923. // If all went well, we should have a buffer error.
  1924. if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
  1925. {
  1926. // Since ERROR_INSUFFICIENT_BUFFER is really a success
  1927. // for us, we will reset the success flag.
  1928. fSuccess = TRUE;
  1929. // Set the out param if it was specified.
  1930. if (pcchRequired)
  1931. {
  1932. *pcchRequired = cchRequiredSize;
  1933. }
  1934. // If the buffer sent in was large enough, go ahead and use it.
  1935. if (cchId >= cchRequiredSize)
  1936. {
  1937. fSuccess = SetupDiGetDeviceInstanceIdW(hdi, pdeid,
  1938. pszId, cchId, NULL);
  1939. }
  1940. }
  1941. }
  1942. #ifdef DBG // Just being safe
  1943. else
  1944. {
  1945. // This should never happen since we sent in no buffer
  1946. AssertSz(FALSE, "SetupDiGetDeviceInstanceId returned success"
  1947. " even though it was given no buffer");
  1948. }
  1949. #endif // DBG
  1950. // We used SetupApi so we need to convert any errors
  1951. if (!fSuccess)
  1952. {
  1953. hr = HrFromLastWin32Error();
  1954. }
  1955. TraceError("HrSetupDiGetDeviceInstanceId", hr);
  1956. return hr;
  1957. }
  1958. //+--------------------------------------------------------------------------
  1959. //
  1960. // Function: HrSetupDiInstallDevice
  1961. //
  1962. // Purpose: Wrapper for SetupDiInstallDevice
  1963. //
  1964. // Arguments:
  1965. // hdi [in] See SetupApi for more info
  1966. // pdeid [in]
  1967. //
  1968. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  1969. //
  1970. // Author: billbe 26 June 1997
  1971. //
  1972. // Notes:
  1973. //
  1974. HRESULT
  1975. HrSetupDiInstallDevice (
  1976. IN HDEVINFO hdi,
  1977. IN PSP_DEVINFO_DATA pdeid)
  1978. {
  1979. Assert(IsValidHandle(hdi));
  1980. Assert(pdeid);
  1981. HRESULT hr = S_OK;
  1982. // Let SetupApi install the specfied device
  1983. if (!SetupDiInstallDevice (hdi, pdeid))
  1984. {
  1985. hr = HrFromLastWin32Error();
  1986. }
  1987. TraceError("HrSetupDiInstallDevice", hr);
  1988. return hr;
  1989. }
  1990. //+--------------------------------------------------------------------------
  1991. //
  1992. // Function: HrSetupDiOpenDevRegKey
  1993. //
  1994. // Purpose: Return an HKEY to the hardware device's driver instance key
  1995. //
  1996. // Arguments:
  1997. // hdi [in] See SetupApi for more info
  1998. // pdeid [in]
  1999. // dwScope [in]
  2000. // dwHwProfile [in]
  2001. // dwKeyType [in]
  2002. // samDesired [in]
  2003. // phkey [out]
  2004. //
  2005. //
  2006. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2007. //
  2008. // Author: billbe 7 May 1997
  2009. //
  2010. // Notes:
  2011. //
  2012. HRESULT
  2013. HrSetupDiOpenDevRegKey (
  2014. IN HDEVINFO hdi,
  2015. IN PSP_DEVINFO_DATA pdeid,
  2016. IN DWORD dwScope,
  2017. IN DWORD dwHwProfile,
  2018. IN DWORD dwKeyType,
  2019. IN REGSAM samDesired,
  2020. OUT HKEY* phkey)
  2021. {
  2022. Assert(IsValidHandle(hdi));
  2023. Assert(pdeid);
  2024. Assert(phkey);
  2025. // Try to open the registry key
  2026. //
  2027. HRESULT hr;
  2028. HKEY hkey = SetupDiOpenDevRegKey(hdi, pdeid, dwScope, dwHwProfile,
  2029. dwKeyType, samDesired);
  2030. if (INVALID_HANDLE_VALUE != hkey)
  2031. {
  2032. hr = S_OK;
  2033. *phkey = hkey;
  2034. }
  2035. else
  2036. {
  2037. hr = HrFromLastWin32Error();
  2038. *phkey = NULL;
  2039. }
  2040. TraceErrorOptional("HrSetupDiOpenDevRegKey", hr,
  2041. (SPAPI_E_DEVINFO_NOT_REGISTERED == hr) ||
  2042. (SPAPI_E_KEY_DOES_NOT_EXIST == hr));
  2043. return hr;
  2044. }
  2045. //+--------------------------------------------------------------------------
  2046. //
  2047. // Function: HrSetupDiSetClassInstallParams
  2048. //
  2049. // Purpose: sets or clears class install parameters for a device
  2050. // information set or a particular device information element.
  2051. //
  2052. // Arguments:
  2053. // hdi [in] See Device Installer API for more info
  2054. // pdeid [in]
  2055. // pcih [in]
  2056. // cbSize [in]
  2057. //
  2058. //
  2059. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2060. //
  2061. // Author: billbe 26 June 1997
  2062. //
  2063. // Notes:
  2064. //
  2065. HRESULT
  2066. HrSetupDiSetClassInstallParams (
  2067. IN HDEVINFO hdi,
  2068. IN PSP_DEVINFO_DATA pdeid, OPTIONAL
  2069. IN PSP_CLASSINSTALL_HEADER pcih, OPTIONAL
  2070. IN DWORD cbSize)
  2071. {
  2072. Assert(IsValidHandle(hdi));
  2073. HRESULT hr = S_OK;
  2074. // Set or clear the params
  2075. if (!SetupDiSetClassInstallParams(hdi, pdeid, pcih, cbSize))
  2076. {
  2077. hr = HrFromLastWin32Error();
  2078. }
  2079. TraceError("HrSetupDiSetClassInstallParams", hr);
  2080. return hr;
  2081. }
  2082. //+--------------------------------------------------------------------------
  2083. //
  2084. // Function: HrSetupDiGetFixedSizeClassInstallParams
  2085. //
  2086. // Purpose: Gets a fixed size of an info list's ot device's class install
  2087. // parameters for a device.
  2088. //
  2089. // Arguments:
  2090. // hdi [in] See Device Installer for more info
  2091. // pdeid [in]
  2092. // pcih [in]
  2093. // cbSize [in]
  2094. //
  2095. //
  2096. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2097. //
  2098. // Author: billbe 26 June 1997
  2099. //
  2100. // Notes:
  2101. //
  2102. HRESULT
  2103. HrSetupDiGetFixedSizeClassInstallParams (
  2104. IN HDEVINFO hdi,
  2105. IN PSP_DEVINFO_DATA pdeid,
  2106. IN PSP_CLASSINSTALL_HEADER pcih,
  2107. IN INT cbSize)
  2108. {
  2109. Assert(IsValidHandle(hdi));
  2110. Assert(pcih);
  2111. HRESULT hr = S_OK;
  2112. ZeroMemory(pcih, cbSize);
  2113. pcih->cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  2114. // Device Installer Api uses an all purpose GetClassInstallParams
  2115. // function. Several structures contain an SP_CLASSINSTALL_HEADER
  2116. // as their first member.
  2117. if (!SetupDiGetClassInstallParams(hdi, pdeid, pcih, cbSize, NULL))
  2118. {
  2119. hr = HrFromLastWin32Error();
  2120. }
  2121. TraceErrorOptional("HrSetupDiGetFixedSizeClassInstallParams", hr,
  2122. SPAPI_E_NO_CLASSINSTALL_PARAMS == hr);
  2123. return hr;
  2124. }
  2125. //+--------------------------------------------------------------------------
  2126. //
  2127. // Function: HrSetupDiGetSelectedDriver
  2128. //
  2129. // Purpose: Retrieves the member of a driver list that has been selected
  2130. // as the controlling driver.
  2131. //
  2132. // Arguments:
  2133. // hdi [in] See SetupApi for more info
  2134. // pdeid [in]
  2135. // pdrid [out]
  2136. //
  2137. //
  2138. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2139. //
  2140. // Author: billbe 26 June 1997
  2141. //
  2142. // Notes:
  2143. //
  2144. HRESULT
  2145. HrSetupDiGetSelectedDriver (
  2146. IN HDEVINFO hdi,
  2147. IN PSP_DEVINFO_DATA pdeid,
  2148. OUT PSP_DRVINFO_DATA pdrid)
  2149. {
  2150. Assert(IsValidHandle(hdi));
  2151. Assert(pdrid);
  2152. // initialize and set the cbSize field
  2153. ZeroMemory(pdrid, sizeof(*pdrid));
  2154. pdrid->cbSize = sizeof(*pdrid);
  2155. HRESULT hr = S_OK;
  2156. // Set pdrid as the selected driver
  2157. if (!SetupDiGetSelectedDriver(hdi, pdeid, pdrid))
  2158. {
  2159. hr = HrFromLastWin32Error();
  2160. }
  2161. TraceError("HrSetupDiGetSelectedDriver",
  2162. (SPAPI_E_NO_DRIVER_SELECTED == hr) ? S_OK : hr);
  2163. return hr;
  2164. }
  2165. //+---------------------------------------------------------------------------
  2166. //
  2167. // Function: HrSetupDiGetDriverInfoDetail
  2168. //
  2169. // Purpose: Gets details on the driver referenced by the given parameters.
  2170. //
  2171. // Arguments:
  2172. // hdi []
  2173. // pdeid [] See SetupAPI for more info
  2174. // pdrid []
  2175. // ppdridd []
  2176. //
  2177. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2178. //
  2179. // Author: danielwe 5 May 1998
  2180. //
  2181. // Notes:
  2182. //
  2183. HRESULT
  2184. HrSetupDiGetDriverInfoDetail (
  2185. IN HDEVINFO hdi,
  2186. IN PSP_DEVINFO_DATA pdeid,
  2187. IN PSP_DRVINFO_DATA pdrid,
  2188. OUT PSP_DRVINFO_DETAIL_DATA* ppdridd)
  2189. {
  2190. HRESULT hr = S_OK;
  2191. BOOL fSuccess = TRUE;
  2192. DWORD dwRequiredSize = 0;
  2193. Assert(IsValidHandle(hdi));
  2194. Assert(pdrid);
  2195. Assert(ppdridd);
  2196. Assert(pdrid);
  2197. *ppdridd = NULL;
  2198. // Get the size needed for the driver detail
  2199. if (!(fSuccess = SetupDiGetDriverInfoDetailW (hdi, pdeid, pdrid, NULL,
  2200. 0, &dwRequiredSize)))
  2201. {
  2202. // We should have received an insufficient buffer error since we
  2203. // sent no buffer
  2204. if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
  2205. {
  2206. // Since this is ERROR_INSUFFICIENT_BUFFER is really a
  2207. // success for us, we will reset the success flag.
  2208. fSuccess = TRUE;
  2209. // Now we allocate our buffer for the driver detail data
  2210. // The size of the buffer is variable but it is a
  2211. // PSP_DEVINFO_DETAIL_DATA.
  2212. *ppdridd = (PSP_DRVINFO_DETAIL_DATA)MemAlloc (dwRequiredSize);
  2213. if (*ppdridd)
  2214. {
  2215. //initialize the variable
  2216. ZeroMemory(*ppdridd, dwRequiredSize);
  2217. (*ppdridd)->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  2218. // Get detailed info
  2219. fSuccess = SetupDiGetDriverInfoDetailW (hdi, pdeid, pdrid,
  2220. *ppdridd, dwRequiredSize, NULL);
  2221. }
  2222. else
  2223. {
  2224. hr = E_OUTOFMEMORY;
  2225. }
  2226. }
  2227. }
  2228. else
  2229. {
  2230. // This should NEVER happen
  2231. AssertSz(FALSE, "HrSetupDiGetDriverInfoDetail succeeded with no "
  2232. "buffer!");
  2233. }
  2234. // We have been using Device Installer Api so convert any errors
  2235. if (!fSuccess)
  2236. {
  2237. hr = HrFromLastWin32Error();
  2238. }
  2239. // clean up on failure
  2240. if (FAILED(hr))
  2241. {
  2242. MemFree (*ppdridd);
  2243. *ppdridd = NULL;
  2244. }
  2245. TraceError("HrSetupDiGetDriverInfoDetail", hr);
  2246. return hr;
  2247. }
  2248. //+--------------------------------------------------------------------------
  2249. //
  2250. // Function: HrSetupDiSetSelectedDriver
  2251. //
  2252. // Purpose: Sets the specified member of a driver list as the
  2253. // currently-selected driver. It can also be used to reset
  2254. // the driver list so that there is no currently-selected
  2255. // driver.
  2256. //
  2257. // Arguments:
  2258. // hdi [in] See SetupApi for more info
  2259. // pdeid [in]
  2260. // pdrid [in, out]
  2261. //
  2262. //
  2263. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2264. //
  2265. // Author: billbe 26 June 1997
  2266. //
  2267. // Notes:
  2268. //
  2269. HRESULT
  2270. HrSetupDiSetSelectedDriver (
  2271. IN HDEVINFO hdi,
  2272. IN PSP_DEVINFO_DATA pdeid,
  2273. IN OUT PSP_DRVINFO_DATA pdrid)
  2274. {
  2275. Assert(IsValidHandle(hdi));
  2276. Assert(pdrid);
  2277. HRESULT hr = S_OK;
  2278. // Set pdrid as the selected driver
  2279. if (!SetupDiSetSelectedDriver(hdi, pdeid, pdrid))
  2280. {
  2281. hr = HrFromLastWin32Error();
  2282. }
  2283. TraceError("HrSetupDiSetSelectedDriver", hr);
  2284. return hr;
  2285. }
  2286. //+--------------------------------------------------------------------------
  2287. //
  2288. // Function: HrSetupDiCreateDevRegKey
  2289. //
  2290. // Purpose: Creates and returns an HKEY to the hardware device's driver
  2291. // instance key
  2292. //
  2293. // Arguments:
  2294. // hdi [in] See SetupApi for more info
  2295. // pdeid [in]
  2296. // dwScope [in]
  2297. // dwHwProfile [in]
  2298. // dwKeyType [in]
  2299. // hinf [in] OPTIONAL
  2300. // pszInfSectionName [in] OPTIONAL
  2301. // phkey [out]
  2302. //
  2303. //
  2304. // Returns: HRESULT. S_OK if successful, Win32 error code otherwise
  2305. //
  2306. // Author: billbe 4 June 1997
  2307. //
  2308. // Notes:
  2309. //
  2310. HRESULT
  2311. HrSetupDiCreateDevRegKey (
  2312. IN HDEVINFO hdi,
  2313. IN PSP_DEVINFO_DATA pdeid,
  2314. IN DWORD dwScope,
  2315. IN DWORD dwHwProfile,
  2316. IN DWORD dwKeyType,
  2317. IN HINF hinf,
  2318. PCWSTR pszInfSectionName,
  2319. OUT HKEY* phkey)
  2320. {
  2321. Assert(IsValidHandle(hdi));
  2322. Assert(pdeid);
  2323. Assert(phkey);
  2324. // Try to create the registry key and process the inf section, if
  2325. // specified
  2326. //
  2327. HRESULT hr;
  2328. HKEY hkey = SetupDiCreateDevRegKeyW(hdi, pdeid, dwScope, dwHwProfile,
  2329. dwKeyType, hinf, pszInfSectionName);
  2330. if (INVALID_HANDLE_VALUE != hkey)
  2331. {
  2332. hr = S_OK;
  2333. *phkey = hkey;
  2334. }
  2335. else
  2336. {
  2337. hr = HrFromLastWin32Error();
  2338. *phkey = NULL;
  2339. }
  2340. TraceError("HrSetupDiCreateDevRegKey", hr);
  2341. return hr;
  2342. }
  2343. //+--------------------------------------------------------------------------
  2344. //
  2345. // Function: HrSetupDiGetActualSectionToInstall
  2346. //
  2347. // Purpose: The sections in an inf file may have OS and platform suffixes
  2348. // appended to them. This function searches for a section that
  2349. // has pszSectionName as its base and has a certain suffix.
  2350. // For example on an x86 NT machine, given a section name of
  2351. // INSTALL, the search would start with INSTALL.NTx86, if that
  2352. // is not found, then INSTALL.NT is searched for.
  2353. // If that is not found INSTALL is returned.
  2354. //
  2355. // Arguments:
  2356. // hinf [in] SetupApi inf file handle
  2357. // pszSectionName [in] the section name to base the search on
  2358. // pstrActualSectionName [out] The actual section name with extension
  2359. // pstrExtension [out] OPTIONAL. The extension part of the
  2360. // pstrActualSectionName.
  2361. // This includes "."
  2362. //
  2363. //
  2364. // Returns: HRESULT. S_OK if successful, error code otherwise
  2365. //
  2366. // Author: billbe 27 Mar 1997
  2367. //
  2368. // Notes: See SetupDiGetActualSectionToInstall in SetupApi documention
  2369. // for more info
  2370. //
  2371. HRESULT
  2372. HrSetupDiGetActualSectionToInstall(
  2373. IN HINF hinf,
  2374. IN PCWSTR pszSectionName,
  2375. OUT tstring* pstrActualSectionName,
  2376. OUT tstring* pstrExtension OPTIONAL)
  2377. {
  2378. Assert(IsValidHandle(hinf));
  2379. Assert(pszSectionName);
  2380. Assert(pstrActualSectionName);
  2381. // strSectionName might need to be decorated with OS
  2382. // and Platform specific suffixes. The next call will return the actual
  2383. // decorated section name or our current section name if the decorated
  2384. // one does not exist.
  2385. //
  2386. BOOL fSuccess = TRUE;
  2387. DWORD cchRequiredSize;
  2388. // Get the buffer length required
  2389. if (fSuccess = SetupDiGetActualSectionToInstallW(hinf,
  2390. pszSectionName, NULL, 0, &cchRequiredSize, NULL))
  2391. {
  2392. // now we allocate space to get the actual section name
  2393. // we allocate on the stack for automatic clean-up
  2394. // Note: dwRequiredSize includes the terminating NULL
  2395. //
  2396. PWSTR pszActualSection = NULL;
  2397. pszActualSection = (PWSTR)_alloca(cchRequiredSize * sizeof(WCHAR));
  2398. PWSTR pszExtension = NULL;
  2399. // Now fill the temporary and assign it to the OUT parameter
  2400. if (fSuccess = SetupDiGetActualSectionToInstallW(hinf,
  2401. pszSectionName, pszActualSection, cchRequiredSize,
  2402. NULL, &pszExtension))
  2403. {
  2404. *pstrActualSectionName = pszActualSection;
  2405. // If the user wants the extension assign it to the string
  2406. // or assign the empty string if no extension was found
  2407. if (pstrExtension)
  2408. {
  2409. *pstrExtension = (pszExtension ? pszExtension : c_szEmpty);
  2410. }
  2411. }
  2412. else
  2413. {
  2414. // initialize out params on failure
  2415. pstrActualSectionName->erase();
  2416. if (pstrExtension)
  2417. {
  2418. pstrExtension->erase();
  2419. }
  2420. }
  2421. }
  2422. // We used SetupApi so errors have to be converted
  2423. HRESULT hr = S_OK;
  2424. if (!fSuccess)
  2425. {
  2426. hr = HrFromLastWin32Error();
  2427. }
  2428. TraceError("HrSetupDiGetActualSectionToInstall", hr);
  2429. return hr;
  2430. }
  2431. //+--------------------------------------------------------------------------
  2432. //
  2433. // Function: HrSetupDiGetActualSectionToInstallWithAlloc
  2434. //
  2435. // Purpose: The sections in an inf file may have OS and platform suffixes
  2436. // appended to them. This function searches for a section that
  2437. // has pszSectionName as its base and has a certain suffix.
  2438. // For example on an x86 NT machine, given a section name of
  2439. // INSTALL, the search would start with INSTALL.NTx86, if that
  2440. // is not found, then INSTALL.NT is searched for.
  2441. // If that is not found INSTALL is returned.
  2442. //
  2443. // Arguments:
  2444. // hinf [in] SetupApi inf file handle.
  2445. // pszSection [in] the section name to base the search on.
  2446. // ppszActualSection [out] The actual section name with extension.
  2447. // If the actual section is the same as
  2448. // pszSectionName, *ppszActualSectionName
  2449. // will be NULL.
  2450. // ppszExtension [out] OPTIONAL. The extension part of the
  2451. // *ppszActualSectionName. This includes "."
  2452. //
  2453. //
  2454. // Returns: HRESULT. S_OK if successful, error code otherwise
  2455. //
  2456. // Author: billbe 27 Mar 1997
  2457. //
  2458. // Notes: See SetupDiGetActualSectionToInstall in SetupApi documention
  2459. // for more info
  2460. //
  2461. HRESULT
  2462. HrSetupDiGetActualSectionToInstallWithAlloc(
  2463. IN HINF hinf,
  2464. IN PWSTR pszSection,
  2465. OUT PWSTR* ppszActualSection,
  2466. OUT PWSTR* ppszExtension OPTIONAL)
  2467. {
  2468. Assert(IsValidHandle(hinf));
  2469. Assert(pszSection);
  2470. Assert(ppszActualSection);
  2471. // pszSectionName might need to be decorated with OS
  2472. // and Platform specific suffixes. The next call will return the actual
  2473. // decorated section name or our current section name if the decorated
  2474. // one does not exist.
  2475. //
  2476. HRESULT hr = S_OK;
  2477. BOOL fSuccess = TRUE;
  2478. DWORD cchRequiredSize;
  2479. *ppszActualSection = NULL;
  2480. if (ppszExtension)
  2481. {
  2482. *ppszExtension = NULL;
  2483. }
  2484. // Get the buffer length required
  2485. if (fSuccess = SetupDiGetActualSectionToInstallW(hinf,
  2486. pszSection, NULL, 0, &cchRequiredSize, NULL))
  2487. {
  2488. // We are assuming the section is not changing. If cchRequired is
  2489. // larger than the current section name buffer than we will allocate
  2490. // and fill the out param.
  2491. //
  2492. // If the section name is teh same, then we will not allocate. But
  2493. // if ppszExtension is specified then we need to send in the original
  2494. // section name buffer since ppszExtension will point to a location
  2495. // within it.
  2496. //
  2497. PWSTR pszBuffer = pszSection;
  2498. if ((wcslen(pszSection) + 1) < cchRequiredSize)
  2499. {
  2500. hr = E_OUTOFMEMORY;
  2501. *ppszActualSection = new WCHAR[cchRequiredSize * sizeof(WCHAR)];
  2502. pszBuffer = *ppszActualSection;
  2503. }
  2504. // if the section name is different (we allocated) or the
  2505. // extension out param was specified, then we need to call the fcn.
  2506. if (pszBuffer && ((pszBuffer != pszSection) || ppszExtension))
  2507. {
  2508. // Now fill the temporary and assign it to the OUT parameter
  2509. if (!(fSuccess = SetupDiGetActualSectionToInstallW(hinf,
  2510. pszSection, pszBuffer, cchRequiredSize,
  2511. NULL, ppszExtension)))
  2512. {
  2513. // initialize out params on failure
  2514. delete [] *ppszActualSection;
  2515. *ppszActualSection = NULL;
  2516. if (ppszExtension)
  2517. {
  2518. *ppszExtension = NULL;
  2519. }
  2520. }
  2521. }
  2522. }
  2523. // We used SetupApi so errors have to be converted
  2524. if (SUCCEEDED(hr) && !fSuccess)
  2525. {
  2526. hr = HrFromLastWin32Error();
  2527. }
  2528. TraceError("HrSetupDiGetActualSectionToInstallWithAlloc", hr);
  2529. return hr;
  2530. }
  2531. //+--------------------------------------------------------------------------
  2532. //
  2533. // Function: HrSetupDiGetActualSectionToInstallWithBuffer
  2534. //
  2535. // Purpose: The sections in an inf file may have OS and platform suffixes
  2536. // appended to them. This function searches for a section that
  2537. // has pszSectionName as its base and has a certain suffix.
  2538. // For example on an x86 NT machine, given a section name of
  2539. // INSTALL, the search would start with INSTALL.NTx86, if that
  2540. // is not found, then INSTALL.NT is searched for.
  2541. // If that is not found INSTALL is returned.
  2542. //
  2543. // Arguments:
  2544. // hinf [in] SetupApi inf file handle.
  2545. // pszSection [in] The section name to base the search on.
  2546. // pszActualSection [out] The actual section name with extension
  2547. // Buffer must be LINE_LEN characters.
  2548. // cchActualSection [in] Size of pszActualSection in characters.
  2549. // pcchRequired [out] OPTIONAL. Reuqired size of buffer in
  2550. // characters.
  2551. // ppszExtension [out] OPTIONAL. The extension part of the
  2552. // pszActualSection. This includes "."
  2553. //
  2554. //
  2555. // Returns: HRESULT. S_OK if successful, error code otherwise
  2556. //
  2557. // Author: billbe 27 Mar 1997
  2558. //
  2559. // Notes: See SetupDiGetActualSectionToInstall in SetupApi documention
  2560. // for more info
  2561. //
  2562. HRESULT
  2563. HrSetupDiGetActualSectionToInstallWithBuffer(
  2564. IN HINF hinf,
  2565. IN PCWSTR pszSection,
  2566. OUT PWSTR pszActualSection,
  2567. IN DWORD cchActualSection,
  2568. OUT DWORD* pcchRequired,
  2569. OUT PWSTR* ppszExtension OPTIONAL)
  2570. {
  2571. Assert(IsValidHandle(hinf));
  2572. Assert(pszSection);
  2573. Assert(pszActualSection);
  2574. // pszSectionName might need to be decorated with OS
  2575. // and Platform specific suffixes. The next call will return the actual
  2576. // decorated section name or our current section name if the decorated
  2577. // one does not exist.
  2578. //
  2579. BOOL fSuccess = TRUE;
  2580. DWORD cchRequiredSize;
  2581. *pszActualSection = 0;
  2582. if (ppszExtension)
  2583. {
  2584. *ppszExtension = NULL;
  2585. }
  2586. // Get the buffer length required
  2587. if (fSuccess = SetupDiGetActualSectionToInstallW(hinf,
  2588. pszSection, NULL, 0, &cchRequiredSize, NULL))
  2589. {
  2590. if (pcchRequired)
  2591. {
  2592. *pcchRequired = cchRequiredSize;
  2593. }
  2594. // If the buffer sent in is large enough, get the section name.
  2595. if (cchActualSection >= cchRequiredSize)
  2596. {
  2597. if (!(fSuccess = SetupDiGetActualSectionToInstallW(hinf,
  2598. pszSection, pszActualSection, cchActualSection,
  2599. NULL, ppszExtension)))
  2600. {
  2601. // cleanup on failure.
  2602. *pszActualSection = 0;
  2603. }
  2604. }
  2605. }
  2606. // We used SetupApi so errors have to be converted
  2607. HRESULT hr = S_OK;
  2608. if (!fSuccess)
  2609. {
  2610. hr = HrFromLastWin32Error();
  2611. }
  2612. TraceError("HrSetupDiGetActualSectionToInstallWithBuffer", hr);
  2613. return hr;
  2614. }
  2615. //+--------------------------------------------------------------------------
  2616. //
  2617. // Function: HrSetupDiGetDeviceInstallParams
  2618. //
  2619. // Purpose: Returns the device install params header of a
  2620. // device info set/data. Set SetupDiGetDeviceInstallParams
  2621. // in the SetupApi for more info.
  2622. //
  2623. // Arguments:
  2624. // hdi [in] See SetupApi for more info
  2625. // pdeid [in] See SetupApi for more info
  2626. // pdeip [out] See SetupApi for more info
  2627. //
  2628. // Returns: HRESULT. S_OK if successful, error code otherwise
  2629. //
  2630. // Author: billbe 26 May 1997
  2631. //
  2632. // Notes: This function will clear the variable pdeip and set its
  2633. // cbSize field.
  2634. //
  2635. HRESULT
  2636. HrSetupDiGetDeviceInstallParams (
  2637. IN HDEVINFO hdi,
  2638. IN PSP_DEVINFO_DATA pdeid, OPTIONAL
  2639. OUT PSP_DEVINSTALL_PARAMS pdeip)
  2640. {
  2641. Assert(IsValidHandle(hdi));
  2642. Assert(pdeip);
  2643. HRESULT hr = S_OK;
  2644. // initialize out parameter and set its cbSize field
  2645. //
  2646. ZeroMemory(pdeip, sizeof(SP_DEVINSTALL_PARAMS));
  2647. pdeip->cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  2648. // get the header
  2649. if (!SetupDiGetDeviceInstallParams(hdi, pdeid, pdeip))
  2650. {
  2651. hr = HrFromLastWin32Error();
  2652. }
  2653. TraceError("HrSetupDiGetDeviceInstallParams", hr);
  2654. return hr;
  2655. }
  2656. //+--------------------------------------------------------------------------
  2657. //
  2658. // Function: HrSetupDiGetDriverInstallParams
  2659. //
  2660. // Purpose: Retrieves install parameters for the specified driver.
  2661. // See SetupApi for more info.
  2662. //
  2663. // Arguments:
  2664. // hdi [in] See SetupApi for more info
  2665. // pdeid [in]
  2666. // pdrid [in]
  2667. // pdrip [out]
  2668. //
  2669. // Returns: HRESULT. S_OK if successful, error code otherwise
  2670. //
  2671. // Author: billbe 26 June 1997
  2672. //
  2673. // Notes: This function will clear the variable pdrip and set its
  2674. // cbSize field.
  2675. //
  2676. HRESULT
  2677. HrSetupDiGetDriverInstallParams (
  2678. IN HDEVINFO hdi,
  2679. IN PSP_DEVINFO_DATA pdeid, OPTIONAL
  2680. IN PSP_DRVINFO_DATA pdrid,
  2681. OUT PSP_DRVINSTALL_PARAMS pdrip)
  2682. {
  2683. Assert(IsValidHandle(hdi));
  2684. Assert(pdrid);
  2685. Assert(pdrip);
  2686. HRESULT hr = S_OK;
  2687. // initialize out parameter and set its cbSize field
  2688. //
  2689. ZeroMemory(pdrip, sizeof(SP_DRVINSTALL_PARAMS));
  2690. pdrip->cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  2691. // get the header
  2692. if (!SetupDiGetDriverInstallParams(hdi, pdeid, pdrid, pdrip))
  2693. {
  2694. hr = HrFromLastWin32Error();
  2695. }
  2696. TraceError("HrSetupDiGetDriverInstallParams", hr);
  2697. return hr;
  2698. }
  2699. VOID
  2700. SetupDiSetConfigFlags (
  2701. IN HDEVINFO hdi,
  2702. IN PSP_DEVINFO_DATA pdeid,
  2703. IN DWORD dwFlags,
  2704. IN SD_FLAGS_BINARY_OP eOp)
  2705. {
  2706. DWORD dwConfigFlags = 0;
  2707. // Get the current config flags
  2708. (VOID) HrSetupDiGetDeviceRegistryProperty(hdi, pdeid,
  2709. SPDRP_CONFIGFLAGS, NULL, (BYTE*)&dwConfigFlags,
  2710. sizeof(dwConfigFlags), NULL);
  2711. // Perform the requested operation
  2712. switch (eOp)
  2713. {
  2714. case SDFBO_AND:
  2715. dwConfigFlags &= dwFlags;
  2716. break;
  2717. case SDFBO_OR:
  2718. dwConfigFlags |= dwFlags;
  2719. break;
  2720. case SDFBO_XOR:
  2721. dwConfigFlags ^= dwFlags;
  2722. break;
  2723. default:
  2724. AssertSz(FALSE, "Invalid binary op in HrSetupDiSetConfigFlags");
  2725. }
  2726. (VOID) HrSetupDiSetDeviceRegistryProperty(hdi, pdeid, SPDRP_CONFIGFLAGS,
  2727. (BYTE*)&dwConfigFlags, sizeof(dwConfigFlags));
  2728. }
  2729. //+--------------------------------------------------------------------------
  2730. //
  2731. // Function: HrSetupDiSetDeviceInstallParams
  2732. //
  2733. // Purpose: Sets the device install params header of a
  2734. // device info set/data. Set SetupDiSetDeviceInstallParams
  2735. // in the SetupApi for more info.
  2736. //
  2737. // Arguments:
  2738. // hdi [in] See SetupApi for more info
  2739. // pdeid [in] See SetupApi for more info
  2740. // pdeip [in] See SetupApi for more info
  2741. //
  2742. // Returns: HRESULT. S_OK if successful, error code otherwise
  2743. //
  2744. // Author: billbe 26 May 1997
  2745. //
  2746. // Notes:
  2747. //
  2748. HRESULT
  2749. HrSetupDiSetDeviceInstallParams (
  2750. IN HDEVINFO hdi,
  2751. IN PSP_DEVINFO_DATA pdeid, OPTIONAL
  2752. IN PSP_DEVINSTALL_PARAMS pdeip)
  2753. {
  2754. Assert(IsValidHandle(hdi));
  2755. Assert(pdeip);
  2756. Assert(pdeip->cbSize == sizeof(SP_DEVINSTALL_PARAMS));
  2757. HRESULT hr = S_OK;
  2758. // set the header
  2759. if (!SetupDiSetDeviceInstallParams(hdi, pdeid, pdeip))
  2760. {
  2761. hr = HrFromLastWin32Error();
  2762. }
  2763. TraceError("HrSetupDiSetDeviceInstallParams", hr);
  2764. return hr;
  2765. }
  2766. //+--------------------------------------------------------------------------
  2767. //
  2768. // Function: HrSetupDiSetDriverInstallParams
  2769. //
  2770. // Purpose: Establishes install parameters for the specified driver.
  2771. //
  2772. // Arguments:
  2773. // hdi [in] See SetupApi for more info
  2774. // pdeid [in]
  2775. // pdrid [in]
  2776. // pdrip [in]
  2777. //
  2778. // Returns: HRESULT. S_OK if successful, error code otherwise
  2779. //
  2780. // Author: billbe 26 June 1997
  2781. //
  2782. // Notes:
  2783. //
  2784. HRESULT
  2785. HrSetupDiSetDriverInstallParams (
  2786. IN HDEVINFO hdi,
  2787. IN PSP_DEVINFO_DATA pdeid, OPTIONAL
  2788. IN PSP_DRVINFO_DATA pdrid,
  2789. IN PSP_DRVINSTALL_PARAMS pdrip)
  2790. {
  2791. Assert(IsValidHandle(hdi));
  2792. Assert(pdrid);
  2793. Assert(pdrip);
  2794. Assert(pdrip->cbSize == sizeof(SP_DRVINSTALL_PARAMS));
  2795. HRESULT hr = S_OK;
  2796. // set the header
  2797. if (!SetupDiSetDriverInstallParams(hdi, pdeid, pdrid, pdrip))
  2798. {
  2799. hr = HrFromLastWin32Error();
  2800. }
  2801. TraceError("HrSetupDiSetDriverInstallParams", hr);
  2802. return hr;
  2803. }
  2804. //+--------------------------------------------------------------------------
  2805. //
  2806. // Function: HrSetupDiSetDeipFlags
  2807. //
  2808. // Purpose: This sets given flags in a dev info data
  2809. //
  2810. // Arguments:
  2811. // hdi [in] See Device Installer Api for more info
  2812. // pdeid [in] See Device Installer Api for more info
  2813. // dwFlags [in] Flags to set
  2814. // eFlagType [in] Which flags field to set with dwFlags
  2815. // eClobber [in] Whether to add to existing flags or relace them
  2816. //
  2817. // Returns: HRESULT. S_OK if successful,
  2818. // a Win32 converted error otherwise
  2819. //
  2820. //
  2821. // Author: billbe 3 Feb 1998
  2822. //
  2823. // Notes:
  2824. //
  2825. HRESULT
  2826. HrSetupDiSetDeipFlags (
  2827. IN HDEVINFO hdi,
  2828. IN PSP_DEVINFO_DATA pdeid,
  2829. IN DWORD dwFlags, SD_DEID_FLAG_TYPE eFlagType,
  2830. IN SD_FLAGS_BINARY_OP eOp)
  2831. {
  2832. Assert(IsValidHandle(hdi));
  2833. SP_DEVINSTALL_PARAMS deip;
  2834. // Get the install params
  2835. HRESULT hr = HrSetupDiGetDeviceInstallParams (hdi, pdeid, &deip);
  2836. if (S_OK == hr)
  2837. {
  2838. DWORD* pFlags;
  2839. // Set our pointer to the right flag type
  2840. switch (eFlagType)
  2841. {
  2842. case SDDFT_FLAGS:
  2843. pFlags = &deip.Flags;
  2844. break;
  2845. case SDDFT_FLAGSEX:
  2846. pFlags = &deip.FlagsEx;
  2847. break;
  2848. default:
  2849. AssertSz(FALSE, "Invalid Flag type in HrSetupDiSetDeipFlags");
  2850. break;
  2851. }
  2852. // Perform the requested operation
  2853. switch (eOp)
  2854. {
  2855. case SDFBO_AND:
  2856. *pFlags &= dwFlags;
  2857. break;
  2858. case SDFBO_OR:
  2859. *pFlags |= dwFlags;
  2860. break;
  2861. case SDFBO_XOR:
  2862. *pFlags ^= dwFlags;
  2863. break;
  2864. default:
  2865. AssertSz(FALSE, "Invalid binary op in HrSetupDiSetDeipFlags");
  2866. }
  2867. // update the params
  2868. hr = HrSetupDiSetDeviceInstallParams (hdi, pdeid, &deip);
  2869. }
  2870. TraceError ("HrSetupDiSetDeipFlags", hr);
  2871. return hr;
  2872. }
  2873. //+--------------------------------------------------------------------------
  2874. //
  2875. // Function: HrSetupDiRemoveDevice
  2876. //
  2877. // Purpose: Calls SetupApi to remove a device. See
  2878. // SetupDiRemoveDevice for more info.
  2879. //
  2880. // Arguments:
  2881. // hdi [in] See SetupApi for more info
  2882. // pdeid [in] See SetupApi for more info
  2883. //
  2884. // Returns: HRESULT. S_OK if successful, error code otherwise
  2885. //
  2886. // Author: billbe 27 May 1997
  2887. //
  2888. // Notes: This is used for enumerated Net class components
  2889. //
  2890. HRESULT
  2891. HrSetupDiRemoveDevice(
  2892. IN HDEVINFO hdi,
  2893. IN PSP_DEVINFO_DATA pdeid)
  2894. {
  2895. Assert(IsValidHandle(hdi));
  2896. Assert(pdeid);
  2897. HRESULT hr = S_OK;
  2898. if (!SetupDiRemoveDevice(hdi,pdeid))
  2899. {
  2900. hr = HrFromLastWin32Error();
  2901. }
  2902. TraceError("HrSetupDiRemoveDevice", hr);
  2903. return hr;
  2904. }
  2905. //+--------------------------------------------------------------------------
  2906. //
  2907. // Function: HrSetupDiOpenDeviceInfo
  2908. //
  2909. // Purpose: Retrieves information about an existing device instance and
  2910. // adds it to the specified device information set
  2911. //
  2912. // Arguments:
  2913. // hdi [in] See SetupApi for more info
  2914. // pszPnpInstanceId [in] See SetupApi for more info
  2915. // hwndParent [in] See SetupApi for more info
  2916. // dwOpenFlags [in] See SetupApi for more info
  2917. // pdeid [out] See SetupApi for more info OPTIONAL
  2918. //
  2919. // Returns: HRESULT. S_OK if successful, error code otherwise
  2920. //
  2921. // Author: billbe 27 May 1997
  2922. //
  2923. // Notes: This is used for enumerated Net class components
  2924. //
  2925. HRESULT
  2926. HrSetupDiOpenDeviceInfo(
  2927. IN const HDEVINFO hdi,
  2928. IN PCWSTR pszPnpInstanceId,
  2929. IN HWND hwndParent,
  2930. IN DWORD dwOpenFlags,
  2931. OUT PSP_DEVINFO_DATA pdeid OPTIONAL)
  2932. {
  2933. Assert(IsValidHandle(hdi));
  2934. Assert(pszPnpInstanceId);
  2935. // If the out param was specified, clear it and set its cbSize field
  2936. //
  2937. if (pdeid)
  2938. {
  2939. ZeroMemory(pdeid, sizeof(*pdeid));
  2940. pdeid->cbSize = sizeof(*pdeid);
  2941. }
  2942. HRESULT hr = S_OK;
  2943. if (!SetupDiOpenDeviceInfo(hdi, pszPnpInstanceId, hwndParent, dwOpenFlags,
  2944. pdeid))
  2945. {
  2946. hr = HrFromLastWin32Error();
  2947. }
  2948. TraceHr (ttidError, FAL, hr, SPAPI_E_NO_SUCH_DEVINST == hr,
  2949. "HrSetupDiOpenDeviceInfo");
  2950. return hr;
  2951. }
  2952. //+--------------------------------------------------------------------------
  2953. //
  2954. // Function: HrSetupDiCreateDeviceInfoList
  2955. //
  2956. // Purpose: Creates an empty device information set.
  2957. //
  2958. // Arguments:
  2959. // pguidClass [in] See SetupApi for more info
  2960. // hwndParent [in] See SetupApi for more info
  2961. // phdi [out] See SetupApi for more info
  2962. //
  2963. // Returns: HRESULT. S_OK if successful, error code otherwise
  2964. //
  2965. // Author: billbe 27 May 1997
  2966. //
  2967. // Notes:
  2968. //
  2969. HRESULT
  2970. HrSetupDiCreateDeviceInfoList (
  2971. IN const GUID* pguidClass,
  2972. IN HWND hwndParent,
  2973. OUT HDEVINFO* phdi)
  2974. {
  2975. Assert(phdi);
  2976. HRESULT hr;
  2977. // Try to create the info set
  2978. //
  2979. HDEVINFO hdi = SetupDiCreateDeviceInfoList (pguidClass, hwndParent);
  2980. if (INVALID_HANDLE_VALUE != hdi)
  2981. {
  2982. hr = S_OK;
  2983. *phdi = hdi;
  2984. }
  2985. else
  2986. {
  2987. hr = HrFromLastWin32Error();
  2988. *phdi = NULL;
  2989. }
  2990. TraceError("HrSetupDiCreateDeviceInfoList", hr);
  2991. return hr;
  2992. }
  2993. //+--------------------------------------------------------------------------
  2994. //
  2995. // Function: HrSetupDiGetDeviceRegistryPropertyWithAlloc
  2996. //
  2997. // Purpose: Returns the requested property of a device
  2998. // See SetupApi for more info.
  2999. //
  3000. // Arguments:
  3001. // hdi [in] See SetupApi for more info
  3002. // pdeid [in]
  3003. // dwProperty [in]
  3004. // pdwRegType [out]
  3005. // ppbBuffer [out]
  3006. //
  3007. // Returns: HRESULT. S_OK if successful, error code otherwise
  3008. //
  3009. // Author: billbe 1 June 1997
  3010. //
  3011. // Notes:
  3012. //
  3013. HRESULT
  3014. HrSetupDiGetDeviceRegistryPropertyWithAlloc(
  3015. IN HDEVINFO hdi,
  3016. IN PSP_DEVINFO_DATA pdeid,
  3017. IN DWORD dwProperty,
  3018. OUT DWORD* pdwRegType, OPTIONAL
  3019. OUT BYTE** ppbBuffer)
  3020. {
  3021. Assert(IsValidHandle(hdi));
  3022. Assert(pdeid);
  3023. Assert(ppbBuffer);
  3024. *ppbBuffer = NULL;
  3025. DWORD cbReqSize;
  3026. HRESULT hr = S_OK;
  3027. // Get the size needed for the buffer
  3028. BOOL fWin32Success = SetupDiGetDeviceRegistryPropertyW(hdi, pdeid,
  3029. dwProperty, NULL, NULL, 0, &cbReqSize);
  3030. // We expect failure since we want the buffer size and sent in no buffer
  3031. if (!fWin32Success)
  3032. {
  3033. if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
  3034. {
  3035. // Not really an error
  3036. fWin32Success = TRUE;
  3037. }
  3038. if (fWin32Success)
  3039. {
  3040. *ppbBuffer = (BYTE*) MemAlloc (cbReqSize);
  3041. if (*ppbBuffer)
  3042. {
  3043. // Now get the actual information
  3044. fWin32Success = SetupDiGetDeviceRegistryPropertyW(hdi, pdeid,
  3045. dwProperty, pdwRegType, *ppbBuffer, cbReqSize, NULL);
  3046. }
  3047. else
  3048. {
  3049. hr = E_OUTOFMEMORY;
  3050. }
  3051. }
  3052. }
  3053. // All failures are converted to HRESULTS
  3054. if (SUCCEEDED(hr) && !fWin32Success)
  3055. {
  3056. MemFree (*ppbBuffer);
  3057. *ppbBuffer = NULL;
  3058. hr = HrFromLastWin32Error();
  3059. }
  3060. TraceHr (ttidError, FAL, hr ,
  3061. (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr) ||
  3062. (SPAPI_E_NO_SUCH_DEVINST == hr),
  3063. "HrSetupDiGetDeviceRegistryPropertyWithAlloc");
  3064. return hr;
  3065. }
  3066. //+--------------------------------------------------------------------------
  3067. //
  3068. // Function: HrSetupDiGetDeviceRegistryProperty
  3069. //
  3070. // Purpose: Returns the requested property of a device
  3071. // See SetupApi for more info.
  3072. //
  3073. // Arguments:
  3074. // hdi [in] See SetupApi for more info
  3075. // pdeid [in]
  3076. // dwProperty [in]
  3077. // pdwRegType [out]
  3078. // ppbBuffer [out]
  3079. //
  3080. // Returns: HRESULT. S_OK if successful, error code otherwise
  3081. //
  3082. // Author: billbe 1 June 1997
  3083. //
  3084. // Notes:
  3085. //
  3086. HRESULT
  3087. HrSetupDiGetDeviceRegistryProperty(
  3088. IN HDEVINFO hdi,
  3089. IN PSP_DEVINFO_DATA pdeid,
  3090. IN DWORD dwProperty,
  3091. OUT DWORD* pdwRegType, OPTIONAL
  3092. OUT BYTE* pbBuffer,
  3093. IN DWORD cbBufferSize,
  3094. OUT DWORD* pcbRequiredSize OPTIONAL)
  3095. {
  3096. Assert(IsValidHandle(hdi));
  3097. Assert(pdeid);
  3098. // Get the size needed for the buffer
  3099. BOOL fWin32Success = SetupDiGetDeviceRegistryPropertyW(hdi, pdeid, dwProperty,
  3100. pdwRegType, pbBuffer, cbBufferSize, pcbRequiredSize);
  3101. HRESULT hr = S_OK;
  3102. // All failures are converted to HRESULTS
  3103. if (!fWin32Success)
  3104. {
  3105. if (pbBuffer)
  3106. {
  3107. *pbBuffer = 0;
  3108. }
  3109. hr = HrFromLastWin32Error();
  3110. }
  3111. TraceHr (ttidError, FAL, hr ,
  3112. (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr) ||
  3113. (SPAPI_E_NO_SUCH_DEVINST == hr),
  3114. "HrSetupDiGetDeviceRegistryProperty");
  3115. return hr;
  3116. }
  3117. //+---------------------------------------------------------------------------
  3118. //
  3119. // Function: HrSetupDiGetDeviceName
  3120. //
  3121. // Purpose: Helper function to get the name of the device specified in
  3122. // hdi and pdeid. Trys the friendly name first and if not there
  3123. // falls back to driver name which must be there.
  3124. //
  3125. // Arguments:
  3126. // hdi [in]
  3127. // pdeid [in] See SetupApi for more info
  3128. // ppszName [out]
  3129. //
  3130. // Returns: HRESULT. S_OK if successful, error code otherwise
  3131. //
  3132. // Author: danielwe 11 Feb 1998
  3133. //
  3134. // Notes:
  3135. //
  3136. HRESULT
  3137. HrSetupDiGetDeviceName (
  3138. IN HDEVINFO hdi,
  3139. IN PSP_DEVINFO_DATA pdeid,
  3140. OUT PWSTR* ppszName)
  3141. {
  3142. Assert(IsValidHandle(hdi));
  3143. Assert(pdeid);
  3144. Assert(ppszName);
  3145. DWORD dwType;
  3146. HRESULT hr = S_OK;
  3147. hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc(
  3148. hdi, pdeid, SPDRP_FRIENDLYNAME, &dwType, (BYTE**)ppszName);
  3149. if (FAILED(hr))
  3150. {
  3151. // Try again with the device desc which MUST be there.
  3152. hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc(
  3153. hdi, pdeid, SPDRP_DEVICEDESC, &dwType, (BYTE**)ppszName);
  3154. }
  3155. AssertSz(FImplies(SUCCEEDED(hr), (dwType == REG_SZ)), "Not a string?!");
  3156. TraceError("HrSetupDiGetDeviceName", hr);
  3157. return hr;
  3158. }
  3159. //+---------------------------------------------------------------------------
  3160. //
  3161. // Function: HrSetupDiSetDeviceName
  3162. //
  3163. // Purpose: Helper function to set the name of the device specified in
  3164. // hdi and pdeid.
  3165. //
  3166. // Arguments:
  3167. // hdi [in]
  3168. // pdeid [in] See SetupApi for more info
  3169. // ppbBuffer [out]
  3170. //
  3171. // Returns: HRESULT. S_OK if successful, error code otherwise
  3172. //
  3173. // Author: sumitc 23 apr 1998
  3174. //
  3175. // Notes:
  3176. //
  3177. HRESULT
  3178. HrSetupDiSetDeviceName(
  3179. IN HDEVINFO hdi,
  3180. IN PSP_DEVINFO_DATA pdeid,
  3181. IN PCWSTR pszDeviceName)
  3182. {
  3183. Assert(IsValidHandle(hdi));
  3184. Assert(pszDeviceName);
  3185. HRESULT hr = S_OK;
  3186. hr = HrSetupDiSetDeviceRegistryProperty(hdi,
  3187. pdeid,
  3188. SPDRP_FRIENDLYNAME,
  3189. (const BYTE*)pszDeviceName,
  3190. sizeof(WCHAR) * (wcslen(pszDeviceName) + 1));
  3191. TraceError("HrSetupDiSetDeviceName", hr);
  3192. return hr;
  3193. }
  3194. //+--------------------------------------------------------------------------
  3195. //
  3196. // Function: HrSetupDiSetDeviceRegistryProperty
  3197. //
  3198. // Purpose: Sets the specified Plug and Play device registry property.
  3199. // See SetupApi for more info.
  3200. //
  3201. // Arguments:
  3202. // hdi [in] See SetupApi for more info
  3203. // pdeid [in]
  3204. // dwProperty [in]
  3205. // pbBuffer [in]
  3206. // cbSize [in]
  3207. //
  3208. // Returns: HRESULT. S_OK if successful, error code otherwise
  3209. //
  3210. // Author: billbe 26 June 1997
  3211. //
  3212. // Notes:
  3213. //
  3214. HRESULT
  3215. HrSetupDiSetDeviceRegistryProperty(IN HDEVINFO hdi,
  3216. IN OUT PSP_DEVINFO_DATA pdeid,
  3217. IN DWORD dwProperty,
  3218. IN const BYTE* pbBuffer,
  3219. IN DWORD cbSize)
  3220. {
  3221. Assert(IsValidHandle(hdi));
  3222. Assert(pdeid);
  3223. Assert(pbBuffer);
  3224. HRESULT hr = S_OK;
  3225. // Set the property
  3226. if (!SetupDiSetDeviceRegistryProperty(hdi, pdeid, dwProperty, pbBuffer,
  3227. cbSize))
  3228. {
  3229. hr = HrFromLastWin32Error();
  3230. }
  3231. TraceError("HrSetupDiSetDeviceRegistryProperty", hr);
  3232. return hr;
  3233. }
  3234. //+--------------------------------------------------------------------------
  3235. //
  3236. // Function: HrSetupDiSendPropertyChangeNotification
  3237. //
  3238. // Purpose: This sends a DIF_PROPERTCHANGE notification to the
  3239. // class installer
  3240. //
  3241. // Arguments:
  3242. // hdi [in] See Device Isntaller Api
  3243. // pdeid [in]
  3244. // dwStateChange [in]
  3245. // dwScope [in]
  3246. // dwProfileId [in]
  3247. //
  3248. // Returns: HRESULT. S_OK if no error, a Win32 error converted
  3249. // code otherwise
  3250. //
  3251. // Author: billbe 4 Nov 1997
  3252. //
  3253. // Notes:
  3254. //
  3255. HRESULT
  3256. HrSetupDiSendPropertyChangeNotification(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid,
  3257. DWORD dwStateChange, DWORD dwScope,
  3258. DWORD dwProfileId)
  3259. {
  3260. Assert(IsValidHandle(hdi));
  3261. Assert(pdeid);
  3262. // First we create the property change structure and fill out its fields
  3263. //
  3264. SP_PROPCHANGE_PARAMS pcp;
  3265. ZeroMemory(&pcp, sizeof(pcp));
  3266. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  3267. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  3268. pcp.StateChange = dwStateChange;
  3269. pcp.Scope = dwScope;
  3270. pcp.HwProfile = dwProfileId;
  3271. // Now we set the structure as the device info data's
  3272. // class install params
  3273. HRESULT hr = HrSetupDiSetClassInstallParams(hdi, pdeid,
  3274. reinterpret_cast<SP_CLASSINSTALL_HEADER*>(&pcp),
  3275. sizeof(pcp));
  3276. if (SUCCEEDED(hr))
  3277. {
  3278. // Now we need to set the "we have a class install params" flag
  3279. // in the device install params
  3280. //
  3281. SP_DEVINSTALL_PARAMS deip;
  3282. hr = HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip);
  3283. if (SUCCEEDED(hr))
  3284. {
  3285. deip.Flags |= DI_CLASSINSTALLPARAMS;
  3286. hr = HrSetupDiSetDeviceInstallParams(hdi, pdeid, &deip);
  3287. if (SUCCEEDED(hr))
  3288. {
  3289. // Notify the driver that the state has changed
  3290. hr = HrSetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hdi,
  3291. pdeid);
  3292. if (SUCCEEDED(hr))
  3293. {
  3294. // Set the properties change flag in the device info to
  3295. // let anyone who cares know that their ui might need
  3296. // updating to reflect any change in the device's status
  3297. // We can't let any failures here stop us so we ignore
  3298. // return values
  3299. //
  3300. (void) HrSetupDiGetDeviceInstallParams(hdi, pdeid,
  3301. &deip);
  3302. deip.Flags |= DI_PROPERTIES_CHANGE;
  3303. (void) HrSetupDiSetDeviceInstallParams(hdi, pdeid,
  3304. &deip);
  3305. }
  3306. }
  3307. }
  3308. }
  3309. TraceError("HrSetupDiSendPropertyChangeNotification", hr);
  3310. return hr;
  3311. }
  3312. //+--------------------------------------------------------------------------
  3313. //
  3314. // Function: FSetupDiCheckIfRestartNeeded
  3315. //
  3316. // Purpose: Checks the hdi and pdeid for the presence of the
  3317. // restart flag in the install params structure.
  3318. // See Device Installer Api for more info.
  3319. //
  3320. // Arguments:
  3321. // hdi [in] See Device Installer Api
  3322. // pdeid [in]
  3323. //
  3324. // Returns: BOOL. TRUE if a restart is required, FALSE otherwise
  3325. //
  3326. // Author: billbe 28 Apr 1997
  3327. //
  3328. // Notes:
  3329. //
  3330. BOOL
  3331. FSetupDiCheckIfRestartNeeded(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid)
  3332. {
  3333. Assert(IsValidHandle(hdi));
  3334. Assert(pdeid);
  3335. SP_DEVINSTALL_PARAMS deip;
  3336. BOOL fRestart = FALSE;
  3337. // Get the install params for the device pdeid.
  3338. HRESULT hr = HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip);
  3339. if (SUCCEEDED(hr))
  3340. {
  3341. // Check for the presence of the flag
  3342. if ((deip.Flags & DI_NEEDRESTART) || (deip.Flags & DI_NEEDREBOOT))
  3343. {
  3344. fRestart = TRUE;
  3345. }
  3346. }
  3347. // We don't return any failures from this function since it is just
  3348. // a check but we should trace them
  3349. TraceError("FSetupDiCheckIfRestartNeeded", hr);
  3350. return fRestart;
  3351. }
  3352. //+--------------------------------------------------------------------------
  3353. //
  3354. // Function: HrSetupDiGetClassImageList
  3355. //
  3356. // Purpose: Builds an image list that contains bitmaps for every
  3357. // installed class and returns the list in a data structure
  3358. //
  3359. // Arguments:
  3360. // pcild [out] See Device Installer Api for more info
  3361. //
  3362. // Returns: HRESULT. S_OK if successful, error code otherwise
  3363. //
  3364. // Author: billbe 26 Nov 1997
  3365. //
  3366. // Notes: The image list will be in the ImageList field of the pcild
  3367. // structure
  3368. //
  3369. HRESULT
  3370. HrSetupDiGetClassImageList(PSP_CLASSIMAGELIST_DATA pcild)
  3371. {
  3372. Assert(pcild);
  3373. HRESULT hr = S_OK;
  3374. ZeroMemory(pcild, sizeof(*pcild));
  3375. pcild->cbSize = sizeof(*pcild);
  3376. if (!SetupDiGetClassImageList(pcild))
  3377. {
  3378. hr = HrFromLastWin32Error();
  3379. }
  3380. TraceError("HrSetupDiGetClassImageList", hr);
  3381. return hr;
  3382. }
  3383. //+--------------------------------------------------------------------------
  3384. //
  3385. // Function: HrSetupDiDestroyClassImageList
  3386. //
  3387. // Purpose: Destroys a class image list that was built with
  3388. // (Hr)SetupDiGetClassImageList
  3389. //
  3390. // Arguments:
  3391. // pcild [in] See Device Installer Api for more info
  3392. //
  3393. // Returns: HRESULT. S_OK if successful, error code otherwise
  3394. //
  3395. // Author: billbe 26 Nov 1997
  3396. //
  3397. // Notes:
  3398. //
  3399. HRESULT
  3400. HrSetupDiDestroyClassImageList(PSP_CLASSIMAGELIST_DATA pcild)
  3401. {
  3402. Assert(pcild);
  3403. HRESULT hr = S_OK;
  3404. if (!SetupDiDestroyClassImageList(pcild))
  3405. {
  3406. hr = HrFromLastWin32Error();
  3407. }
  3408. TraceError("HrSetupDiDestroyClassImageList", hr);
  3409. return hr;
  3410. }
  3411. //+--------------------------------------------------------------------------
  3412. //
  3413. // Function: HrSetupDiGetClassImageIndex
  3414. //
  3415. // Purpose: Retrieves the index within the class image list of a
  3416. // specified class
  3417. //
  3418. // Arguments:
  3419. // pcild [in] See Device Installer Api for more info
  3420. // guidClass [in]
  3421. // pnIndex [out]
  3422. //
  3423. // Returns: HRESULT. S_OK if successful, error code otherwise
  3424. //
  3425. // Author: billbe 26 Nov 1997
  3426. //
  3427. // Notes:
  3428. //
  3429. HRESULT
  3430. HrSetupDiGetClassImageIndex(PSP_CLASSIMAGELIST_DATA pcild,
  3431. const GUID* pguidClass, INT* pnIndex)
  3432. {
  3433. Assert(pcild);
  3434. Assert(pguidClass);
  3435. Assert(pnIndex);
  3436. HRESULT hr = S_OK;
  3437. if (!SetupDiGetClassImageIndex(pcild, pguidClass, pnIndex))
  3438. {
  3439. hr = HrFromLastWin32Error();
  3440. }
  3441. TraceError("HrSetupDiGetClassImageIndex", hr);
  3442. return hr;
  3443. }
  3444. //+--------------------------------------------------------------------------
  3445. //
  3446. // Function: HrSetupDiGetParentWindow
  3447. //
  3448. // Purpose: Returns the window handle found in the install params of a
  3449. // device info set/data. Set SP_DEVINSTALL_PARAMS in the
  3450. // SetupApi for more info.
  3451. //
  3452. // Arguments:
  3453. // hdi [in] See SetupApi for more info
  3454. // pdeid [in] See SetupApi for more info
  3455. // phwndParent [out] Pointer to the parent window handle
  3456. //
  3457. // Returns: HRESULT. S_OK if successful, error code otherwise
  3458. //
  3459. // Author: billbe 12 May 1997
  3460. //
  3461. // Notes:
  3462. //
  3463. HRESULT HrSetupDiGetParentWindow (HDEVINFO hdi,
  3464. PSP_DEVINFO_DATA pdeid, OPTIONAL
  3465. HWND* phwndParent)
  3466. {
  3467. Assert(IsValidHandle(hdi));
  3468. Assert(phwndParent);
  3469. // Initialize the output parameter.
  3470. *phwndParent = NULL;
  3471. // Get the install params of the device
  3472. SP_DEVINSTALL_PARAMS deip;
  3473. HRESULT hr = HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip);
  3474. if (SUCCEEDED(hr))
  3475. {
  3476. // Only assign the output if we have a valid window handle
  3477. if (IsWindow(deip.hwndParent))
  3478. {
  3479. *phwndParent = deip.hwndParent;
  3480. }
  3481. }
  3482. TraceError("HrSetupDiGetParentWindow", hr);
  3483. return hr;
  3484. }
  3485. //+--------------------------------------------------------------------------
  3486. //
  3487. // Function: HrSetupInstallFilesFromInfSection
  3488. //
  3489. // Purpose: Queues all the files specified in the Copy Files sections
  3490. // listed by an Install section for installation.
  3491. //
  3492. // Arguments:
  3493. // hinf [in] See SetupApi for more info
  3494. // hinfLayout [in] Optional
  3495. // hfq [in]
  3496. // pszSection [in]
  3497. // pszSourcePath [in] Optional
  3498. // ulFlags [in] Optional
  3499. //
  3500. // Returns: HRESULT. S_OK if successful, error code otherwise
  3501. //
  3502. // Author: billbe 21 July 1997
  3503. //
  3504. // Notes:
  3505. //
  3506. HRESULT
  3507. HrSetupInstallFilesFromInfSection (
  3508. IN HINF hinf,
  3509. IN HINF hinfLayout,
  3510. IN HSPFILEQ hfq,
  3511. IN PCWSTR pszSection,
  3512. IN PCWSTR pszSourcePath,
  3513. IN UINT ulFlags)
  3514. {
  3515. Assert(IsValidHandle(hinf));
  3516. Assert(FImplies(hinfLayout, INVALID_HANDLE_VALUE != hinfLayout));
  3517. Assert(pszSection);
  3518. HRESULT hr = S_OK;
  3519. if (!SetupInstallFilesFromInfSection(hinf, hinfLayout, hfq, pszSection,
  3520. pszSourcePath, ulFlags))
  3521. {
  3522. hr = HrFromLastWin32Error();
  3523. }
  3524. TraceError("HrSetupInstallFilesFromInfSection", hr);
  3525. return hr;
  3526. }
  3527. //+--------------------------------------------------------------------------
  3528. //
  3529. // Function: HrSetupInstallFromInfSection
  3530. //
  3531. // Purpose: Carries out all the directives in an INF file Install section.
  3532. //
  3533. // Arguments:
  3534. // hwnd [in] See SetupApi for more info
  3535. // hinf [in]
  3536. // pszSection [in]
  3537. // ulFlags [in]
  3538. // hkey [in]
  3539. // pszSource [in]
  3540. // ulCopyFlags [in]
  3541. // pfc [in]
  3542. // pvCtx [in]
  3543. // hdi [in]
  3544. // pdeid [in]
  3545. //
  3546. // Returns: HRESULT. S_OK if successful, error code otherwise
  3547. //
  3548. // Author: billbe 5 July 1997
  3549. //
  3550. // Notes:
  3551. //
  3552. HRESULT
  3553. HrSetupInstallFromInfSection (
  3554. IN HWND hwnd,
  3555. IN HINF hinf,
  3556. IN PCWSTR pszSection,
  3557. IN UINT ulFlags,
  3558. IN HKEY hkey,
  3559. IN PCWSTR pszSource,
  3560. IN UINT ulCopyFlags,
  3561. IN PSP_FILE_CALLBACK pfc,
  3562. IN PVOID pvCtx,
  3563. IN HDEVINFO hdi,
  3564. IN PSP_DEVINFO_DATA pdeid)
  3565. {
  3566. Assert(IsValidHandle(hinf));
  3567. Assert(pszSection);
  3568. HRESULT hr = S_OK;
  3569. if (!SetupInstallFromInfSection(hwnd, hinf, pszSection, ulFlags, hkey,
  3570. pszSource, ulCopyFlags, pfc, pvCtx, hdi, pdeid))
  3571. {
  3572. hr = HrFromLastWin32Error();
  3573. }
  3574. TraceHr (ttidError, FAL, hr, FALSE, "HrSetupInstallFromInfSection (%S)",
  3575. pszSection);
  3576. return hr;
  3577. }
  3578. //+--------------------------------------------------------------------------
  3579. //
  3580. // Function: HrSetupInstallServicesFromInfSection
  3581. //
  3582. // Purpose: Carries out all the service directives in an INF file Install
  3583. // section.
  3584. //
  3585. // Arguments:
  3586. // hinf [in] See SetupApi for more info
  3587. // pszSection [in]
  3588. // dwFlags [in]
  3589. //
  3590. // Returns: HRESULT. S_OK if successful, error code otherwise
  3591. //
  3592. // Author: billbe 19 Feb 1998
  3593. //
  3594. // Notes:
  3595. //
  3596. HRESULT
  3597. HrSetupInstallServicesFromInfSection (
  3598. IN HINF hinf,
  3599. IN PCWSTR pszSection,
  3600. IN DWORD dwFlags)
  3601. {
  3602. Assert(IsValidHandle(hinf));
  3603. Assert(pszSection);
  3604. HRESULT hr = S_OK;
  3605. if (!SetupInstallServicesFromInfSection(hinf, pszSection, dwFlags))
  3606. {
  3607. hr = HrFromLastWin32Error();
  3608. }
  3609. TraceHr (ttidError, FAL, hr, (SPAPI_E_SECTION_NOT_FOUND == hr),
  3610. "HrSetupInstallServicesFromInfSection (%S)", pszSection);
  3611. return hr;
  3612. }
  3613. //+---------------------------------------------------------------------------
  3614. //
  3615. // Function: HrOpenSoftwareDeviceEnumerator
  3616. //
  3617. // Purpose: Opens the swenum device driver used to install software-
  3618. // enumerated device drivers.
  3619. //
  3620. // Arguments:
  3621. // dwFlagsAndAttributes [in] See CreateFile.
  3622. // phFile [out] The returned handle to the swenum device.
  3623. //
  3624. // Returns: S_OK or an error code.
  3625. //
  3626. // Author: shaunco 30 Mar 1998
  3627. //
  3628. // Notes:
  3629. //
  3630. HRESULT
  3631. HrOpenSoftwareDeviceEnumerator (
  3632. DWORD dwFlagsAndAttributes,
  3633. HANDLE* phFile)
  3634. {
  3635. Assert (phFile);
  3636. // Initialize the output parameter.
  3637. //
  3638. *phFile = INVALID_HANDLE_VALUE;
  3639. // Get the devices in software device enumerator class. There should
  3640. // only be one. (Or rather, we're only interested in the first one.)
  3641. //
  3642. HDEVINFO hdi;
  3643. HRESULT hr = HrSetupDiGetClassDevs (&BUSID_SoftwareDeviceEnumerator,
  3644. NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE,
  3645. &hdi);
  3646. if (S_OK == hr)
  3647. {
  3648. // Enumerate the first device in this class. This will
  3649. // initialize did.
  3650. //
  3651. SP_DEVICE_INTERFACE_DATA did;
  3652. ZeroMemory (&did, sizeof(did));
  3653. did.cbSize = sizeof(did);
  3654. if (SetupDiEnumDeviceInterfaces (hdi, NULL,
  3655. const_cast<LPGUID>(&BUSID_SoftwareDeviceEnumerator),
  3656. 0, &did))
  3657. {
  3658. // Now get the details so we can open the device.
  3659. //
  3660. const ULONG cbDetail = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  3661. (MAX_PATH * sizeof(WCHAR));
  3662. PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
  3663. hr = HrMalloc (cbDetail, (PVOID*)&pDetail);
  3664. if (S_OK == hr)
  3665. {
  3666. pDetail->cbSize = sizeof(*pDetail);
  3667. if (SetupDiGetDeviceInterfaceDetail (hdi, &did,
  3668. pDetail, cbDetail, NULL, NULL))
  3669. {
  3670. // Now open the device (swenum).
  3671. //
  3672. HANDLE hFile = CreateFile (pDetail->DevicePath,
  3673. GENERIC_READ | GENERIC_WRITE,
  3674. 0, NULL, OPEN_EXISTING,
  3675. dwFlagsAndAttributes, NULL);
  3676. if (hFile && (INVALID_HANDLE_VALUE != hFile))
  3677. {
  3678. *phFile = hFile;
  3679. }
  3680. else
  3681. {
  3682. hr = HrFromLastWin32Error ();
  3683. }
  3684. }
  3685. else
  3686. {
  3687. hr = HrFromLastWin32Error ();
  3688. }
  3689. MemFree (pDetail);
  3690. }
  3691. }
  3692. else
  3693. {
  3694. hr = HrFromLastWin32Error ();
  3695. }
  3696. SetupDiDestroyDeviceInfoList (hdi);
  3697. }
  3698. TraceHr (ttidError, FAL, hr, FALSE, "HrOpenSoftwareDeviceEnumerator");
  3699. return hr;
  3700. }
  3701. //+---------------------------------------------------------------------------
  3702. //
  3703. // Function: HrFindDeviceOnInterface
  3704. //
  3705. // Purpose: Searches for a specific device on a given interface.
  3706. // It does this by using setup api to return all of the
  3707. // devices in the class given by pguidInterfaceId. It then
  3708. // gets device path for each of these device interfaces and
  3709. // looks for pguidDeviceId and pszReferenceString as substrings.
  3710. //
  3711. // Arguments:
  3712. // pguidDeviceId [in] The device id to find.
  3713. // pguidInterfaceId [in] The interface on which to look.
  3714. // pszReferenceString [in] Optional. Further match on this ref string.
  3715. // dwFlagsAndAttributes [in] See CreateFile. This is how the device is
  3716. // opened if it is found.
  3717. // phFile [out] The returned device handle.
  3718. //
  3719. // Returns: S_OK if found and opened, S_FALSE if not found, or an error.
  3720. //
  3721. // Author: shaunco 30 Mar 1998
  3722. //
  3723. // Notes:
  3724. //
  3725. HRESULT
  3726. HrFindDeviceOnInterface (
  3727. IN const GUID* pguidDeviceId,
  3728. IN const GUID* pguidInterfaceId,
  3729. IN PCWSTR pszReferenceString,
  3730. IN DWORD dwFlagsAndAttributes,
  3731. OUT HANDLE* phFile)
  3732. {
  3733. Assert (pguidDeviceId);
  3734. Assert (pguidInterfaceId);
  3735. Assert (phFile);
  3736. // Initialize the output parameter.
  3737. //
  3738. *phFile = INVALID_HANDLE_VALUE;
  3739. WCHAR szDeviceId [c_cchGuidWithTerm];
  3740. INT cch = StringFromGUID2 (*pguidDeviceId, szDeviceId,
  3741. c_cchGuidWithTerm);
  3742. Assert (c_cchGuidWithTerm == cch);
  3743. CharLower (szDeviceId);
  3744. // Get the devices in this class.
  3745. //
  3746. HDEVINFO hdi;
  3747. HRESULT hr = HrSetupDiGetClassDevs (pguidInterfaceId, NULL, NULL,
  3748. DIGCF_PRESENT | DIGCF_INTERFACEDEVICE, &hdi);
  3749. if (S_OK == hr)
  3750. {
  3751. BOOL fFound = FALSE;
  3752. // abBuffer is a buffer used to get device interface detail for each
  3753. // device interface enumerated below.
  3754. //
  3755. const ULONG cbDetail = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  3756. (MAX_PATH * sizeof(WCHAR));
  3757. PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
  3758. hr = HrMalloc (cbDetail, (PVOID*)&pDetail);
  3759. if (S_OK == hr)
  3760. {
  3761. // Enumerate the device interfaces looking for the one specified.
  3762. //
  3763. SP_DEVICE_INTERFACE_DATA did;
  3764. ZeroMemory (&did, sizeof(did));
  3765. for (DWORD i = 0;
  3766. did.cbSize = sizeof(did),
  3767. SetupDiEnumDeviceInterfaces (hdi, NULL,
  3768. const_cast<LPGUID>(pguidInterfaceId), i, &did);
  3769. i++)
  3770. {
  3771. // Now get the details so we can compare the device path.
  3772. //
  3773. pDetail->cbSize = sizeof(*pDetail);
  3774. if (SetupDiGetDeviceInterfaceDetailW (hdi, &did,
  3775. pDetail, cbDetail, NULL, NULL))
  3776. {
  3777. CharLower (pDetail->DevicePath);
  3778. // Look for a substring containing szDeviceId. Also
  3779. // look for a substring containing pszReferenceString if
  3780. // it is specified.
  3781. //
  3782. if (wcsstr (pDetail->DevicePath, szDeviceId) &&
  3783. (!pszReferenceString || !*pszReferenceString ||
  3784. wcsstr (pDetail->DevicePath, pszReferenceString)))
  3785. {
  3786. // We found it, so open the device and return it.
  3787. //
  3788. HANDLE hFile = CreateFile (pDetail->DevicePath,
  3789. GENERIC_READ | GENERIC_WRITE,
  3790. 0, NULL, OPEN_EXISTING,
  3791. dwFlagsAndAttributes, NULL);
  3792. if (hFile && (INVALID_HANDLE_VALUE != hFile))
  3793. {
  3794. TraceTag (ttidNetcfgBase, "Found device id '%S'",
  3795. szDeviceId);
  3796. TraceTag (ttidNetcfgBase, "Opening device '%S'",
  3797. pDetail->DevicePath);
  3798. *phFile = hFile;
  3799. fFound = TRUE;
  3800. }
  3801. else
  3802. {
  3803. hr = HrFromLastWin32Error ();
  3804. }
  3805. // Now that we've found it, break out of the loop.
  3806. //
  3807. break;
  3808. }
  3809. }
  3810. else
  3811. {
  3812. hr = HrFromLastWin32Error ();
  3813. }
  3814. }
  3815. MemFree (pDetail);
  3816. }
  3817. SetupDiDestroyDeviceInfoList (hdi);
  3818. if (SUCCEEDED(hr) && !fFound)
  3819. {
  3820. hr = S_FALSE;
  3821. }
  3822. }
  3823. TraceHr(ttidError, FAL, hr, S_FALSE == hr,
  3824. "HrFindDeviceOnInterface (device=%S)", szDeviceId);
  3825. return hr;
  3826. }
  3827. //+---------------------------------------------------------------------------
  3828. //
  3829. // Function: HrInstallSoftwareDeviceOnInterface
  3830. //
  3831. // Purpose: Install a software-enumerated device on the given interface.
  3832. //
  3833. // Arguments:
  3834. // pguidDeviceId [in] The device id to install.
  3835. // pguidInterfaceId [in] The interface to install it on.
  3836. // pszReferenceString [in] The reference string.
  3837. // fForceInstall [in] Usually specify FALSE. Specify TRUE to
  3838. // force installation of the device using
  3839. // pguidClass and pszHardwareId.
  3840. // Typically this is used during GUI mode setup
  3841. // where swenum won't be able to fully install
  3842. // the device.
  3843. //
  3844. // Returns: S_OK or an error code.
  3845. //
  3846. // Author: shaunco 30 Mar 1998
  3847. //
  3848. // Notes:
  3849. //
  3850. HRESULT
  3851. HrInstallSoftwareDeviceOnInterface (
  3852. const GUID* pguidDeviceId,
  3853. const GUID* pguidInterfaceId,
  3854. PCWSTR pszReferenceString,
  3855. BOOL fForceInstall,
  3856. PCWSTR pszInfFilename,
  3857. HWND hwndParent)
  3858. {
  3859. Assert (pguidDeviceId);
  3860. Assert (pguidInterfaceId);
  3861. Assert (pszReferenceString && *pszReferenceString);
  3862. // Open the software device enumerator.
  3863. //
  3864. HANDLE hSwenum;
  3865. HRESULT hr = HrOpenSoftwareDeviceEnumerator (
  3866. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  3867. &hSwenum);
  3868. if (S_OK == hr)
  3869. {
  3870. Assert (INVALID_HANDLE_VALUE != hSwenum);
  3871. // Allocate and build the buffer used as the IOCTL parameter.
  3872. //
  3873. const ULONG cbBuf = (ULONG)FIELD_OFFSET (SWENUM_INSTALL_INTERFACE, ReferenceString) +
  3874. CbOfSzAndTerm (pszReferenceString);
  3875. SWENUM_INSTALL_INTERFACE* pBuf;
  3876. hr = HrMalloc (cbBuf, (PVOID*)&pBuf);
  3877. if (S_OK == hr)
  3878. {
  3879. ZeroMemory (pBuf, cbBuf);
  3880. pBuf->DeviceId = *pguidDeviceId;
  3881. pBuf->InterfaceId = *pguidInterfaceId;
  3882. lstrcpyW (pBuf->ReferenceString, pszReferenceString);
  3883. // Create an event to be used for the overlapped IO we are about
  3884. // to issue.
  3885. //
  3886. OVERLAPPED ovl;
  3887. ZeroMemory (&ovl, sizeof(ovl));
  3888. ovl.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  3889. if (ovl.hEvent)
  3890. {
  3891. #ifdef ENABLETRACE
  3892. WCHAR szDeviceId [c_cchGuidWithTerm];
  3893. INT cch = StringFromGUID2 (pBuf->DeviceId, szDeviceId,
  3894. c_cchGuidWithTerm);
  3895. Assert (c_cchGuidWithTerm == cch);
  3896. WCHAR szInterfaceId [c_cchGuidWithTerm];
  3897. cch = StringFromGUID2 (pBuf->InterfaceId, szInterfaceId,
  3898. c_cchGuidWithTerm);
  3899. Assert (c_cchGuidWithTerm == cch);
  3900. TraceTag (ttidNetcfgBase, "Installing software enumerated "
  3901. "device '%S' on interface '%S'",
  3902. szDeviceId, szInterfaceId);
  3903. #endif
  3904. // Issue the install interface IOCTL.
  3905. //
  3906. DWORD cbReturned;
  3907. BOOL fIoResult = DeviceIoControl (hSwenum,
  3908. IOCTL_SWENUM_INSTALL_INTERFACE,
  3909. pBuf, cbBuf, NULL, 0,
  3910. &cbReturned, &ovl);
  3911. if (!fIoResult)
  3912. {
  3913. hr = HrFromLastWin32Error ();
  3914. if (HRESULT_FROM_WIN32 (ERROR_IO_PENDING) == hr)
  3915. {
  3916. // Wait for the IO to complete if it was returned as
  3917. // pending.
  3918. //
  3919. fIoResult = GetOverlappedResult (hSwenum, &ovl,
  3920. &cbReturned, TRUE);
  3921. if (!fIoResult)
  3922. {
  3923. hr = HrFromLastWin32Error ();
  3924. }
  3925. }
  3926. }
  3927. CloseHandle (ovl.hEvent);
  3928. }
  3929. MemFree (pBuf);
  3930. }
  3931. CloseHandle (hSwenum);
  3932. }
  3933. // Force the device to be installed by enumerating it.
  3934. //
  3935. if ((S_OK == hr) && fForceInstall)
  3936. {
  3937. HANDLE hDevice;
  3938. hr = HrFindDeviceOnInterface (
  3939. pguidDeviceId,
  3940. pguidInterfaceId,
  3941. pszReferenceString,
  3942. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  3943. &hDevice);
  3944. if (S_OK == hr)
  3945. {
  3946. CloseHandle (hDevice);
  3947. }
  3948. else if (S_FALSE == hr)
  3949. {
  3950. // We just installed this device, why wasn't it found?
  3951. //
  3952. hr = E_UNEXPECTED;
  3953. }
  3954. }
  3955. TraceHr (ttidError, FAL, hr, FALSE, "HrInstallSoftwareDeviceOnInterface");
  3956. return hr;
  3957. }
  3958. // ----------------------------------------------------------------------
  3959. //
  3960. // Function: HrInstallFromInfSectionInFile
  3961. //
  3962. // Purpose: Open the given INF file and call Setup API to install
  3963. // from the specified section.
  3964. //
  3965. // Arguments:
  3966. // hwndParent [in] handle of parent window
  3967. // szInfName [in] name of INF
  3968. // szSection [in] section name
  3969. // hkeyRelative [in] handle of reg-key to use
  3970. // fQuietInstall [in] TRUE if we shouldn't show UI and use
  3971. // default values, FALSE if we can bother
  3972. // the user with questions and UI
  3973. //
  3974. // Returns: S_OK on success, otherwise an error code
  3975. //
  3976. // Author: kumarp 23-December-97
  3977. //
  3978. // Notes:
  3979. //
  3980. HRESULT HrInstallFromInfSectionInFile (
  3981. IN HWND hwndParent,
  3982. IN PCWSTR pszInfName,
  3983. IN PCWSTR pszSection,
  3984. IN HKEY hkeyRelative,
  3985. IN BOOL fQuietInstall)
  3986. {
  3987. AssertValidReadPtr(pszInfName);
  3988. AssertValidReadPtr(pszSection);
  3989. HRESULT hr;
  3990. HINF hinf;
  3991. hr = HrSetupOpenInfFile(pszInfName, NULL,
  3992. INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf);
  3993. if (S_OK == hr)
  3994. {
  3995. hr = HrSetupInstallFromInfSection (hwndParent, hinf, pszSection,
  3996. SPINST_REGISTRY, hkeyRelative, NULL, 0, NULL, NULL,
  3997. NULL, NULL);
  3998. }
  3999. TraceError("HrInstallInfSectionInfFile", hr);
  4000. return hr;
  4001. }
  4002. #if defined(REMOTE_BOOT)
  4003. //+--------------------------------------------------------------------------
  4004. //
  4005. // Function: HrIsRemoteBootAdapter
  4006. //
  4007. // Purpose: This determines whether the adapter is a remote boot adapter
  4008. //
  4009. // Arguments:
  4010. // hdi [in] See Device Installer Api for more info
  4011. // pdeid [in] See Device Installer Api for more info
  4012. //
  4013. // Returns: HRESULT. S_OK if adapter is a remote boot adapter
  4014. // S_FALSE if adapter is not a remote boot adapter
  4015. // a Win32 converted error otherwise
  4016. //
  4017. //
  4018. // Author: billbe 31 Jan 1998
  4019. //
  4020. // Notes:
  4021. //
  4022. HRESULT
  4023. HrIsRemoteBootAdapter(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid)
  4024. {
  4025. Assert(IsValidHandle(hdi));
  4026. Assert(pdeid);
  4027. DWORD dwConfigFlags;
  4028. // Get the current config flags
  4029. HRESULT hr = HrSetupDiGetDeviceRegistryProperty(hdi, pdeid,
  4030. SPDRP_CONFIGFLAGS, NULL, (BYTE*)&dwConfigFlags,
  4031. sizeof(dwConfigFlags), NULL);
  4032. if (SUCCEEDED(hr))
  4033. {
  4034. if (dwConfigFlags & CONFIGFLAG_NETBOOT_CARD)
  4035. {
  4036. hr = S_OK;
  4037. }
  4038. else
  4039. {
  4040. hr = S_FALSE;
  4041. }
  4042. }
  4043. else if (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr)
  4044. {
  4045. // The device had no config flags, so it isn't a remote boot adapter
  4046. hr = S_FALSE;
  4047. }
  4048. TraceError("HrIsRemoteBootAdapter", (hr == S_FALSE) ? S_OK : hr);
  4049. return hr;
  4050. }
  4051. #endif // defined(REMOTE_BOOT)
  4052. VOID
  4053. SetupDiDestroyDeviceInfoListSafe(HDEVINFO hdi)
  4054. {
  4055. if (IsValidHandle(hdi))
  4056. {
  4057. SetupDiDestroyDeviceInfoList(hdi);
  4058. }
  4059. }
  4060. VOID
  4061. SetupCloseInfFileSafe(HINF hinf)
  4062. {
  4063. if (IsValidHandle(hinf))
  4064. {
  4065. SetupCloseInfFile(hinf);
  4066. }
  4067. }