Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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