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.

4009 lines
141 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. devinst.c
  5. Abstract:
  6. Device Installer routines.
  7. Author:
  8. Lonny McMichael (lonnym) 1-Aug-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Private prototypes.
  15. //
  16. DWORD
  17. pSetupDiGetCoInstallerList(
  18. IN HDEVINFO DeviceInfoSet, OPTIONAL
  19. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  20. IN CONST GUID *ClassGuid, OPTIONAL
  21. IN OUT PDEVINSTALL_PARAM_BLOCK InstallParamBlock,
  22. IN OUT PVERIFY_CONTEXT VerifyContext OPTIONAL
  23. );
  24. //
  25. // Private logging data
  26. // these must be mirrored from setupapi.h
  27. //
  28. static LPCTSTR pSetupDiDifStrings[] = {
  29. NULL, // no DIF code
  30. TEXT("DIF_SELECTDEVICE"),
  31. TEXT("DIF_INSTALLDEVICE"),
  32. TEXT("DIF_ASSIGNRESOURCES"),
  33. TEXT("DIF_PROPERTIES"),
  34. TEXT("DIF_REMOVE"),
  35. TEXT("DIF_FIRSTTIMESETUP"),
  36. TEXT("DIF_FOUNDDEVICE"),
  37. TEXT("DIF_SELECTCLASSDRIVERS"),
  38. TEXT("DIF_VALIDATECLASSDRIVERS"),
  39. TEXT("DIF_INSTALLCLASSDRIVERS"),
  40. TEXT("DIF_CALCDISKSPACE"),
  41. TEXT("DIF_DESTROYPRIVATEDATA"),
  42. TEXT("DIF_VALIDATEDRIVER"),
  43. TEXT("DIF_MOVEDEVICE"), // obsolete
  44. TEXT("DIF_DETECT"),
  45. TEXT("DIF_INSTALLWIZARD"),
  46. TEXT("DIF_DESTROYWIZARDDATA"),
  47. TEXT("DIF_PROPERTYCHANGE"),
  48. TEXT("DIF_ENABLECLASS"),
  49. TEXT("DIF_DETECTVERIFY"),
  50. TEXT("DIF_INSTALLDEVICEFILES"),
  51. TEXT("DIF_UNREMOVE"),
  52. TEXT("DIF_SELECTBESTCOMPATDRV"),
  53. TEXT("DIF_ALLOW_INSTALL"),
  54. TEXT("DIF_REGISTERDEVICE"),
  55. TEXT("DIF_NEWDEVICEWIZARD_PRESELECT"),
  56. TEXT("DIF_NEWDEVICEWIZARD_SELECT"),
  57. TEXT("DIF_NEWDEVICEWIZARD_PREANALYZE"),
  58. TEXT("DIF_NEWDEVICEWIZARD_POSTANALYZE"),
  59. TEXT("DIF_NEWDEVICEWIZARD_FINISHINSTALL"),
  60. TEXT("DIF_UNUSED1"),
  61. TEXT("DIF_INSTALLINTERFACES"),
  62. TEXT("DIF_DETECTCANCEL"),
  63. TEXT("DIF_REGISTER_COINSTALLERS"),
  64. TEXT("DIF_ADDPROPERTYPAGE_ADVANCED"),
  65. TEXT("DIF_ADDPROPERTYPAGE_BASIC"),
  66. TEXT("DIF_RESERVED1"), // aka, DIF_GETWINDOWSUPDATEINFO
  67. TEXT("DIF_TROUBLESHOOTER"),
  68. TEXT("DIF_POWERMESSAGEWAKE"),
  69. TEXT("DIF_ADDREMOTEPROPERTYPAGE_ADVANCED"),
  70. TEXT("DIF_UPDATEDRIVER_UI"),
  71. TEXT("DIF_RESERVED2") // aka, DIF_INTERFACE_TO_DEVICE
  72. //
  73. // append new DIF codes here (don't forget comma's)
  74. //
  75. };
  76. DWORD FilterLevelOnInstallerError(
  77. IN DWORD PrevLevel,
  78. IN DWORD Err)
  79. /*++
  80. Routine Description:
  81. Allow downgrading of error level depending on returned error
  82. from class/co/default installer
  83. and current state
  84. Arguments:
  85. PrevLevel - initial level
  86. Err - error to check
  87. Return Value:
  88. New level
  89. --*/
  90. {
  91. DWORD Level = PrevLevel;
  92. if(Level == DRIVER_LOG_ERROR) {
  93. switch(Err) {
  94. case ERROR_DUPLICATE_FOUND:
  95. //
  96. // not an error as such
  97. //
  98. Level = DRIVER_LOG_WARNING;
  99. break;
  100. case ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION:
  101. //
  102. // if returned during gui-setup
  103. // or during server-side setup
  104. // demote error to warning
  105. //
  106. if(GuiSetupInProgress ||
  107. (GlobalSetupFlags & PSPGF_NONINTERACTIVE)) {
  108. Level = DRIVER_LOG_WARNING;
  109. }
  110. break;
  111. }
  112. }
  113. return Level;
  114. }
  115. //
  116. // ANSI version
  117. //
  118. BOOL
  119. WINAPI
  120. SetupDiGetDeviceInstallParamsA(
  121. IN HDEVINFO DeviceInfoSet,
  122. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  123. OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
  124. )
  125. {
  126. SP_DEVINSTALL_PARAMS_W deviceInstallParams;
  127. DWORD rc;
  128. try {
  129. deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
  130. rc = GLE_FN_CALL(FALSE,
  131. SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
  132. DeviceInfoData,
  133. &deviceInstallParams)
  134. );
  135. if(rc != NO_ERROR) {
  136. leave;
  137. }
  138. rc = pSetupDiDevInstParamsUnicodeToAnsi(&deviceInstallParams,
  139. DeviceInstallParams
  140. );
  141. } except(pSetupExceptionFilter(GetExceptionCode())) {
  142. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  143. }
  144. SetLastError(rc);
  145. return (rc == NO_ERROR);
  146. }
  147. BOOL
  148. WINAPI
  149. SetupDiGetDeviceInstallParams(
  150. IN HDEVINFO DeviceInfoSet,
  151. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  152. OUT PSP_DEVINSTALL_PARAMS DeviceInstallParams
  153. )
  154. /*++
  155. Routine Description:
  156. This routine retrieves installation parameters for a device information set
  157. (globally), or a particular device information element.
  158. Arguments:
  159. DeviceInfoSet - Supplies a handle to the device information set containing
  160. installation parameters to be retrieved.
  161. DeviceInfoData - Optionally, supplies the address of a SP_DEVINFO_DATA
  162. structure containing installation parameters to be retrieved. If this
  163. parameter is not specified, then the installation parameters retrieved
  164. will be associated with the device information set itself (for the
  165. global class driver list).
  166. DeviceInstallParams - Supplies the address of a SP_DEVINSTALL_PARAMS
  167. structure that will receive the installation parameters. The cbSize
  168. field of this structure must be set to the size, in bytes, of a
  169. SP_DEVINSTALL_PARAMS structure before calling this API.
  170. Return Value:
  171. If the function succeeds, the return value is TRUE.
  172. If the function fails, the return value is FALSE. To get extended error
  173. information, call GetLastError.
  174. --*/
  175. {
  176. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  177. DWORD Err;
  178. PDEVINFO_ELEM DevInfoElem;
  179. try {
  180. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  181. Err = ERROR_INVALID_HANDLE;
  182. leave;
  183. }
  184. if(DeviceInfoData) {
  185. //
  186. // Then we are to retrieve installation parameters for a particular
  187. // device.
  188. //
  189. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  190. DeviceInfoData,
  191. NULL))) {
  192. Err = ERROR_INVALID_PARAMETER;
  193. } else {
  194. Err = GetDevInstallParams(pDeviceInfoSet,
  195. &(DevInfoElem->InstallParamBlock),
  196. DeviceInstallParams
  197. );
  198. }
  199. } else {
  200. //
  201. // Retrieve installation parameters for the global class driver list.
  202. //
  203. Err = GetDevInstallParams(pDeviceInfoSet,
  204. &(pDeviceInfoSet->InstallParamBlock),
  205. DeviceInstallParams
  206. );
  207. }
  208. } except(pSetupExceptionFilter(GetExceptionCode())) {
  209. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  210. }
  211. if(pDeviceInfoSet) {
  212. UnlockDeviceInfoSet(pDeviceInfoSet);
  213. }
  214. SetLastError(Err);
  215. return(Err == NO_ERROR);
  216. }
  217. //
  218. // ANSI version
  219. //
  220. BOOL
  221. WINAPI
  222. SetupDiGetClassInstallParamsA(
  223. IN HDEVINFO DeviceInfoSet,
  224. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  225. OUT PSP_CLASSINSTALL_HEADER ClassInstallParams, OPTIONAL
  226. IN DWORD ClassInstallParamsSize,
  227. OUT PDWORD RequiredSize OPTIONAL
  228. )
  229. {
  230. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  231. PDEVINFO_ELEM DevInfoElem;
  232. PDEVINSTALL_PARAM_BLOCK InstallParamBlock;
  233. DI_FUNCTION Function;
  234. DWORD Err;
  235. try {
  236. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  237. Err = ERROR_INVALID_HANDLE;
  238. leave;
  239. }
  240. Err = NO_ERROR; // assume success
  241. if(DeviceInfoData) {
  242. //
  243. // Then we are to retrieve installation parameters for a particular
  244. // device.
  245. //
  246. if(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,DeviceInfoData,NULL)) {
  247. InstallParamBlock = &DevInfoElem->InstallParamBlock;
  248. } else {
  249. Err = ERROR_INVALID_PARAMETER;
  250. leave;
  251. }
  252. } else {
  253. //
  254. // Retrieve installation parameters for the global class driver
  255. // list.
  256. //
  257. InstallParamBlock = &pDeviceInfoSet->InstallParamBlock;
  258. }
  259. //
  260. // While we're in a try/except, go ahead and do some preliminary
  261. // validation on the caller-supplied buffer...
  262. //
  263. if(ClassInstallParams) {
  264. if((ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER)) ||
  265. (ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER))) {
  266. Err = ERROR_INVALID_USER_BUFFER;
  267. leave;
  268. }
  269. } else if(ClassInstallParamsSize) {
  270. Err = ERROR_INVALID_USER_BUFFER;
  271. leave;
  272. }
  273. MYASSERT(InstallParamBlock);
  274. if(InstallParamBlock->ClassInstallHeader) {
  275. Function = InstallParamBlock->ClassInstallHeader->InstallFunction;
  276. } else {
  277. Err = ERROR_NO_CLASSINSTALL_PARAMS;
  278. leave;
  279. }
  280. //
  281. // For DIF_SELECTDEVICE we need special processing since the structure
  282. // that goes with it is ansi/unicode specific.
  283. //
  284. if(Function == DIF_SELECTDEVICE) {
  285. SP_SELECTDEVICE_PARAMS_W SelectDeviceParams;
  286. SelectDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  287. Err = GLE_FN_CALL(FALSE,
  288. SetupDiGetClassInstallParamsW(
  289. DeviceInfoSet,
  290. DeviceInfoData,
  291. (PSP_CLASSINSTALL_HEADER)&SelectDeviceParams,
  292. sizeof(SP_SELECTDEVICE_PARAMS_W),
  293. NULL)
  294. );
  295. if(Err == NO_ERROR) {
  296. //
  297. // We successfully retrieved the Unicode form of the Select
  298. // Device parameters. Store the required size for the ANSI
  299. // version in the output parameter (if requested).
  300. //
  301. if(RequiredSize) {
  302. *RequiredSize = sizeof(SP_SELECTDEVICE_PARAMS_A);
  303. }
  304. if(ClassInstallParamsSize < sizeof(SP_SELECTDEVICE_PARAMS_A)) {
  305. Err = ERROR_INSUFFICIENT_BUFFER;
  306. } else {
  307. Err = pSetupDiSelDevParamsUnicodeToAnsi(
  308. &SelectDeviceParams,
  309. (PSP_SELECTDEVICE_PARAMS_A)ClassInstallParams
  310. );
  311. }
  312. }
  313. } else {
  314. Err = GLE_FN_CALL(FALSE,
  315. SetupDiGetClassInstallParamsW(
  316. DeviceInfoSet,
  317. DeviceInfoData,
  318. ClassInstallParams,
  319. ClassInstallParamsSize,
  320. RequiredSize)
  321. );
  322. }
  323. } except(pSetupExceptionFilter(GetExceptionCode())) {
  324. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  325. }
  326. if(pDeviceInfoSet) {
  327. UnlockDeviceInfoSet(pDeviceInfoSet);
  328. }
  329. SetLastError(Err);
  330. return (Err == NO_ERROR);
  331. }
  332. BOOL
  333. WINAPI
  334. SetupDiGetClassInstallParams(
  335. IN HDEVINFO DeviceInfoSet,
  336. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  337. OUT PSP_CLASSINSTALL_HEADER ClassInstallParams, OPTIONAL
  338. IN DWORD ClassInstallParamsSize,
  339. OUT PDWORD RequiredSize OPTIONAL
  340. )
  341. /*++
  342. Routine Description:
  343. This routine retrieves class installer parameters for a device information
  344. set (globally), or a particular device information element. These
  345. parameters are specific to a particular device installer function code
  346. (DI_FUNCTION) that will be stored in the ClassInstallHeader field located
  347. at the beginning of the parameter buffer.
  348. Arguments:
  349. DeviceInfoSet - Supplies a handle to the device information set containing
  350. class installer parameters to be retrieved.
  351. DeviceInfoData - Optionally, supplies the address of a SP_DEVINFO_DATA
  352. structure containing class installer parameters to be retrieved. If
  353. this parameter is not specified, then the class installer parameters
  354. retrieved will be associated with the device information set itself
  355. (for the global class driver list).
  356. ClassInstallParams - Optionally, supplies the address of a buffer
  357. containing a class install header structure. This structure must have
  358. its cbSize field set to sizeof(SP_CLASSINSTALL_HEADER) on input, or the
  359. buffer is considered to be invalid. On output, the InstallFunction
  360. field will be filled in with the DI_FUNCTION code for the class install
  361. parameters being retrieved, and if the buffer is large enough, it will
  362. receive the class installer parameters structure specific to that
  363. function code.
  364. If this parameter is not specified, then ClassInstallParamsSize must be
  365. zero. This would be done if the caller simply wants to determine how
  366. large a buffer is required.
  367. ClassInstallParamsSize - Supplies the size, in bytes, of the
  368. ClassInstallParams buffer, or zero, if ClassInstallParams is not
  369. supplied. If the buffer is supplied, it must be _at least_ as large as
  370. sizeof(SP_CLASSINSTALL_HEADER).
  371. RequiredSize - Optionally, supplies the address of a variable that receives
  372. the number of bytes required to store the class installer parameters.
  373. Return Value:
  374. If the function succeeds, the return value is TRUE.
  375. If the function fails, the return value is FALSE. To get extended error
  376. information, call GetLastError.
  377. --*/
  378. {
  379. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  380. DWORD Err;
  381. PDEVINFO_ELEM DevInfoElem;
  382. try {
  383. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  384. Err = ERROR_INVALID_HANDLE;
  385. leave;
  386. }
  387. if(DeviceInfoData) {
  388. //
  389. // Then we are to retrieve installation parameters for a particular
  390. // device.
  391. //
  392. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  393. DeviceInfoData,
  394. NULL))) {
  395. Err = ERROR_INVALID_PARAMETER;
  396. } else {
  397. Err = GetClassInstallParams(&(DevInfoElem->InstallParamBlock),
  398. ClassInstallParams,
  399. ClassInstallParamsSize,
  400. RequiredSize
  401. );
  402. }
  403. } else {
  404. //
  405. // Retrieve installation parameters for the global class driver
  406. // list.
  407. //
  408. Err = GetClassInstallParams(&(pDeviceInfoSet->InstallParamBlock),
  409. ClassInstallParams,
  410. ClassInstallParamsSize,
  411. RequiredSize
  412. );
  413. }
  414. } except(pSetupExceptionFilter(GetExceptionCode())) {
  415. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  416. }
  417. if(pDeviceInfoSet) {
  418. UnlockDeviceInfoSet(pDeviceInfoSet);
  419. }
  420. SetLastError(Err);
  421. return (Err == NO_ERROR);
  422. }
  423. DWORD
  424. _SetupDiSetDeviceInstallParams(
  425. IN HDEVINFO DeviceInfoSet,
  426. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  427. IN PSP_DEVINSTALL_PARAMS DeviceInstallParams,
  428. IN BOOL MsgHandlerIsNativeCharWidth
  429. )
  430. {
  431. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  432. DWORD Err;
  433. PDEVINFO_ELEM DevInfoElem;
  434. try {
  435. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  436. Err = ERROR_INVALID_HANDLE;
  437. leave;
  438. }
  439. if(DeviceInfoData) {
  440. //
  441. // Then we are to set installation parameters for a particular
  442. // device.
  443. //
  444. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  445. DeviceInfoData,
  446. NULL))) {
  447. Err = ERROR_INVALID_PARAMETER;
  448. } else {
  449. Err = SetDevInstallParams(pDeviceInfoSet,
  450. DeviceInstallParams,
  451. &(DevInfoElem->InstallParamBlock),
  452. MsgHandlerIsNativeCharWidth
  453. );
  454. }
  455. } else {
  456. //
  457. // Set installation parameters for the global class driver list.
  458. //
  459. Err = SetDevInstallParams(pDeviceInfoSet,
  460. DeviceInstallParams,
  461. &(pDeviceInfoSet->InstallParamBlock),
  462. MsgHandlerIsNativeCharWidth
  463. );
  464. }
  465. } except(pSetupExceptionFilter(GetExceptionCode())) {
  466. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  467. }
  468. if(pDeviceInfoSet) {
  469. UnlockDeviceInfoSet(pDeviceInfoSet);
  470. }
  471. return Err;
  472. }
  473. //
  474. // ANSI version
  475. //
  476. BOOL
  477. WINAPI
  478. SetupDiSetDeviceInstallParamsA(
  479. IN HDEVINFO DeviceInfoSet,
  480. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  481. IN PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
  482. )
  483. {
  484. DWORD Err;
  485. SP_DEVINSTALL_PARAMS_W UnicodeDeviceInstallParams;
  486. try {
  487. Err = pSetupDiDevInstParamsAnsiToUnicode(DeviceInstallParams,
  488. &UnicodeDeviceInstallParams
  489. );
  490. if(Err != NO_ERROR) {
  491. leave;
  492. }
  493. Err = _SetupDiSetDeviceInstallParams(DeviceInfoSet,
  494. DeviceInfoData,
  495. &UnicodeDeviceInstallParams,
  496. FALSE
  497. );
  498. } except(pSetupExceptionFilter(GetExceptionCode())) {
  499. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  500. }
  501. SetLastError(Err);
  502. return (Err == NO_ERROR);
  503. }
  504. BOOL
  505. WINAPI
  506. SetupDiSetDeviceInstallParams(
  507. IN HDEVINFO DeviceInfoSet,
  508. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  509. IN PSP_DEVINSTALL_PARAMS DeviceInstallParams
  510. )
  511. /*++
  512. Routine Description:
  513. This routine sets installation parameters for a device information set
  514. (globally), or a particular device information element.
  515. Arguments:
  516. DeviceInfoSet - Supplies a handle to the device information set containing
  517. installation parameters to be set.
  518. DeviceInfoData - Optionally, supplies the address of a SP_DEVINFO_DATA
  519. structure containing installation parameters to be set. If this
  520. parameter is not specified, then the installation parameters set
  521. will be associated with the device information set itself (for the
  522. global class driver list).
  523. DeviceInstallParams - Supplies the address of a SP_DEVINSTALL_PARAMS
  524. structure containing the new values of the parameters. The cbSize
  525. field of this structure must be set to the size, in bytes, of the
  526. structure before calling this API.
  527. Return Value:
  528. If the function succeeds, the return value is TRUE.
  529. If the function fails, the return value is FALSE. To get extended error
  530. information, call GetLastError.
  531. Remarks:
  532. All parameters will be validated before any changes are made, so a return
  533. status of FALSE indicates that no parameters were modified.
  534. --*/
  535. {
  536. DWORD Err;
  537. try {
  538. Err = _SetupDiSetDeviceInstallParams(DeviceInfoSet,
  539. DeviceInfoData,
  540. DeviceInstallParams,
  541. TRUE
  542. );
  543. } except(pSetupExceptionFilter(GetExceptionCode())) {
  544. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  545. }
  546. SetLastError(Err);
  547. return (Err == NO_ERROR);
  548. }
  549. //
  550. // ANSI version
  551. //
  552. BOOL
  553. WINAPI
  554. SetupDiSetClassInstallParamsA(
  555. IN HDEVINFO DeviceInfoSet,
  556. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  557. IN PSP_CLASSINSTALL_HEADER ClassInstallParams, OPTIONAL
  558. IN DWORD ClassInstallParamsSize
  559. )
  560. {
  561. DWORD Err;
  562. DI_FUNCTION Function;
  563. SP_SELECTDEVICE_PARAMS_W SelectParams;
  564. try {
  565. if(!ClassInstallParams) {
  566. //
  567. // Just pass it on to the unicode version since there's no thunking
  568. // to do. Note that the size must be 0.
  569. //
  570. if(ClassInstallParamsSize) {
  571. Err = ERROR_INVALID_PARAMETER;
  572. leave;
  573. }
  574. Err = GLE_FN_CALL(FALSE,
  575. SetupDiSetClassInstallParamsW(
  576. DeviceInfoSet,
  577. DeviceInfoData,
  578. ClassInstallParams,
  579. ClassInstallParamsSize)
  580. );
  581. } else {
  582. if(ClassInstallParams->cbSize == sizeof(SP_CLASSINSTALL_HEADER)) {
  583. Function = ClassInstallParams->InstallFunction;
  584. } else {
  585. //
  586. // Structure is invalid.
  587. //
  588. Err = ERROR_INVALID_PARAMETER;
  589. leave;
  590. }
  591. //
  592. // DIF_SELECTDEVICE is a special case since it has a structure that
  593. // needs to be translated from ansi to unicode.
  594. //
  595. // DIF_INTERFACE_TO_DEVICE has unicode structure but ansi not
  596. // supported (yet) - internal
  597. //
  598. // Others can just be passed on to the unicode version with no
  599. // changes to the parameters.
  600. //
  601. if(Function == DIF_SELECTDEVICE) {
  602. if(ClassInstallParamsSize >= sizeof(SP_SELECTDEVICE_PARAMS_A)) {
  603. Err = pSetupDiSelDevParamsAnsiToUnicode(
  604. (PSP_SELECTDEVICE_PARAMS_A)ClassInstallParams,
  605. &SelectParams
  606. );
  607. if(Err != NO_ERROR) {
  608. leave;
  609. }
  610. Err = GLE_FN_CALL(FALSE,
  611. SetupDiSetClassInstallParamsW(
  612. DeviceInfoSet,
  613. DeviceInfoData,
  614. (PSP_CLASSINSTALL_HEADER)&SelectParams,
  615. sizeof(SP_SELECTDEVICE_PARAMS_W))
  616. );
  617. } else {
  618. Err = ERROR_INVALID_PARAMETER;
  619. leave;
  620. }
  621. } else if(Function == DIF_INTERFACE_TO_DEVICE) {
  622. Err = ERROR_INVALID_PARAMETER;
  623. leave;
  624. } else {
  625. Err = GLE_FN_CALL(FALSE,
  626. SetupDiSetClassInstallParamsW(
  627. DeviceInfoSet,
  628. DeviceInfoData,
  629. ClassInstallParams,
  630. ClassInstallParamsSize)
  631. );
  632. }
  633. }
  634. //
  635. // If we get to here, then we have called
  636. // SetupDiSetClassInstallParamsW, although the result (stored in Err)
  637. // may be success or failure.
  638. //
  639. } except(pSetupExceptionFilter(GetExceptionCode())) {
  640. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  641. }
  642. SetLastError(Err);
  643. return (Err == NO_ERROR);
  644. }
  645. BOOL
  646. WINAPI
  647. SetupDiSetClassInstallParams(
  648. IN HDEVINFO DeviceInfoSet,
  649. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  650. IN PSP_CLASSINSTALL_HEADER ClassInstallParams, OPTIONAL
  651. IN DWORD ClassInstallParamsSize
  652. )
  653. /*++
  654. Routine Description:
  655. This routine sets (or clears) class installer parameters for a device
  656. information set (globally), or a particular device information element.
  657. Arguments:
  658. DeviceInfoSet - Supplies a handle to the device information set containing
  659. class installer parameters to be set.
  660. DeviceInfoData - Optionally, supplies the address of a SP_DEVINFO_DATA
  661. structure containing class installer parameters to be set. If this
  662. parameter is not specified, then the class installer parameters to be
  663. set will be associated with the device information set itself (for the
  664. global class driver list).
  665. ClassInstallParams - Optionally, supplies the address of a buffer
  666. containing the class installer parameters to be used. The
  667. SP_CLASSINSTALL_HEADER structure at the beginning of the buffer must
  668. have its cbSize field set to be sizeof(SP_CLASSINSTALL_HEADER), and the
  669. InstallFunction field must be set to the DI_FUNCTION code reflecting
  670. the type of parameters supplied in the rest of the buffer.
  671. If this parameter is not supplied, then the current class installer
  672. parameters (if any) will be cleared for the specified device
  673. information set or element.
  674. FUTURE-2002/06/17-lonnym -- Clearing class install params should be targeted
  675. ** Presently, we blindly clear _any_ class install params that have **
  676. ** been set, irrespective of their DIF code association. There **
  677. ** needs to be a way to clear class install params _only_ if the **
  678. ** params are associated with a specified DIF code. **
  679. ClassInstallParamsSize - Supplies the size, in bytes, of the
  680. ClassInstallParams buffer. If the buffer is not supplied (i.e., the
  681. class installer parameters are to be cleared), then this value must be
  682. zero.
  683. Return Value:
  684. If the function succeeds, the return value is TRUE.
  685. If the function fails, the return value is FALSE. To get extended error
  686. information, call GetLastError.
  687. Remarks:
  688. All parameters will be validated before any changes are made, so a return
  689. status of FALSE indicates that no parameters were modified.
  690. A side effect of setting class installer parameters is that the
  691. DI_CLASSINSTALLPARAMS flag is set. If for some reason, it is desired to
  692. set the parameters, but disable their use, then this flag must be cleared
  693. via SetupDiSetDeviceInstallParams.
  694. If the class installer parameters are cleared, then the
  695. DI_CLASSINSTALLPARAMS flag is reset.
  696. --*/
  697. {
  698. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  699. DWORD Err;
  700. PDEVINFO_ELEM DevInfoElem;
  701. try {
  702. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  703. Err = ERROR_INVALID_HANDLE;
  704. leave;
  705. }
  706. if(DeviceInfoData) {
  707. //
  708. // Then we are to set class installer parameters for a particular device.
  709. //
  710. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  711. DeviceInfoData,
  712. NULL))) {
  713. Err = ERROR_INVALID_PARAMETER;
  714. } else {
  715. Err = SetClassInstallParams(pDeviceInfoSet,
  716. ClassInstallParams,
  717. ClassInstallParamsSize,
  718. &(DevInfoElem->InstallParamBlock)
  719. );
  720. }
  721. } else {
  722. //
  723. // Set class installer parameters for the global class driver list.
  724. //
  725. Err = SetClassInstallParams(pDeviceInfoSet,
  726. ClassInstallParams,
  727. ClassInstallParamsSize,
  728. &(pDeviceInfoSet->InstallParamBlock)
  729. );
  730. }
  731. } except(pSetupExceptionFilter(GetExceptionCode())) {
  732. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  733. }
  734. if(pDeviceInfoSet) {
  735. UnlockDeviceInfoSet(pDeviceInfoSet);
  736. }
  737. SetLastError(Err);
  738. return (Err == NO_ERROR);
  739. }
  740. BOOL
  741. WINAPI
  742. SetupDiCallClassInstaller(
  743. IN DI_FUNCTION InstallFunction,
  744. IN HDEVINFO DeviceInfoSet,
  745. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  746. )
  747. /*++
  748. Routine Description:
  749. This routine calls the appropriate class installer with the specified
  750. installer function.
  751. Before calling the class installer, this routine will call any registered
  752. co-device installers (registration is either per-class or per-device;
  753. per-class installers are called first). Any co-installer wishing to be
  754. called back once the class installer has finished installation may return
  755. ERROR_DI_POSTPROCESSING_REQUIRED. Returning NO_ERROR will also allow
  756. installation to continue, but without a post-processing callback.
  757. Returning any other error code will cause the install action to be aborted
  758. (any co-installers already called that have requested post-processing will
  759. be called back, with InstallResult indicating the cause of failure).
  760. After the class installer has performed the installation (or we've done the
  761. default if ERROR_DI_DO_DEFAULT is returned), then we'll call any co-
  762. installers who have requested postprocessing. The list of co-installers is
  763. treated like a stack, so the co-installers called last 'on the way in' are
  764. called first 'on the way out'.
  765. Arguments:
  766. InstallFunction - Class installer function to call. This can be one
  767. of the following values, or any other (class-specific) value:
  768. DIF_SELECTDEVICE - Select a driver to be installed.
  769. DIF_INSTALLDEVICE - Install the driver for the device. (DeviceInfoData
  770. must be specified.)
  771. DIF_ASSIGNRESOURCES - ** PRESENTLY UNUSED ON WINDOWS NT **
  772. DIF_PROPERTIES - Display a properties dialog for the device.
  773. (DeviceInfoData must be specified.)
  774. DIF_REMOVE - Remove the device. (DeviceInfoData must be specified.)
  775. DIF_FIRSTTIMESETUP - Perform first time setup initialization. This
  776. is used only for the global class information associated with
  777. the device information set (i.e., DeviceInfoData not specified).
  778. DIF_FOUNDDEVICE - ** UNUSED ON WINDOWS NT **
  779. DIF_SELECTCLASSDRIVERS - Select drivers for all devices of the class
  780. associated with the device information set or element.
  781. DIF_VALIDATECLASSDRIVERS - Ensure all devices of the class associated
  782. with the device information set or element are ready to be
  783. installed.
  784. DIF_INSTALLCLASSDRIVERS - Install drivers for all devices of the
  785. class associated with the device information set or element.
  786. DIF_CALCDISKSPACE - Compute the amount of disk space required by
  787. drivers.
  788. DIF_DESTROYPRIVATEDATA - Destroy any private date referenced by
  789. the ClassInstallReserved installation parameter for the specified
  790. device information set or element.
  791. DIF_VALIDATEDRIVER - ** UNUSED ON WINDOWS NT **
  792. DIF_MOVEDEVICE - ** OBSOLETE **
  793. DIF_DETECT - Detect any devices of class associated with the device
  794. information set.
  795. DIF_INSTALLWIZARD - Add any pages necessary to the New Device Wizard
  796. for the class associated with the device information set or
  797. element.
  798. ** OBSOLETE--use DIF_NEWDEVICEWIZARD method instead **
  799. DIF_DESTROYWIZARDDATA - Destroy any private data allocated due to
  800. a DIF_INSTALLWIZARD message.
  801. ** OBSOLETE--not needed for DIF_NEWDEVICEWIZARD method **
  802. DIF_PROPERTYCHANGE - The device's properties are changing. The device
  803. is being enabled, disabled, or has had a resource change.
  804. (DeviceInfoData must be specified.)
  805. DIF_ENABLECLASS - ** UNUSED ON WINDOWS NT **
  806. DIF_DETECTVERIFY - The class installer should verify any devices it
  807. previously detected. Non verified devices should be removed.
  808. DIF_INSTALLDEVICEFILES - The class installer should only install the
  809. driver files for the selected device. (DeviceInfoData must be
  810. specified.)
  811. DIF_UNREMOVE - Unremoves a device from the system. (DeviceInfoData
  812. mustbe specified.)
  813. DIF_SELECTBESTCOMPATDRV - Select the best driver from the device
  814. information element's compatible driver list. (DeviceInfoData must
  815. be specified.)
  816. DIF_ALLOW_INSTALL - Determine whether or not the selected driver should
  817. be installed for the device. (DeviceInfoData must be specified.)
  818. DIF_REGISTERDEVICE - The class installer should register the new,
  819. manually-installed, device information element (via
  820. SetupDiRegisterDeviceInfo) including, potentially, doing duplicate
  821. detection via the SPRDI_FIND_DUPS flag. (DeviceInfoData must be
  822. specified.)
  823. DIF_NEWDEVICEWIZARD_PRESELECT - Allows class-/co-installers to supply
  824. wizard pages to be displayed before the Select Device page during
  825. "Add New Hardware" wizard.
  826. DIF_NEWDEVICEWIZARD_SELECT - Allows class-/co-installers to supply
  827. wizard pages to replace the default Select Device wizard page, as
  828. retrieved by SetupDiGetWizardPage(...SPWPT_SELECTDEVICE...)
  829. DIF_NEWDEVICEWIZARD_PREANALYZE - Allows class-/co-installers to supply
  830. wizard pages to be displayed before the analyze page.
  831. DIF_NEWDEVICEWIZARD_POSTANALYZE - Allows class-/co-installers to supply
  832. wizard pages to be displayed after the analyze page.
  833. DIF_NEWDEVICEWIZARD_FINISHINSTALL - Allows class-/co-installers
  834. (including device-specific co-installers) to supply wizard pages to
  835. be displayed after installation of the device has been performed
  836. (i.e., after DIF_INSTALLDEVICE has been processed), but prior to
  837. the wizard's finish page. This message is sent not only for the
  838. "Add New Hardware" wizard, but also for the autodetection and "New
  839. Hardware Found" scenarios as well.
  840. DIF_UNUSED1 - ** PRESENTLY UNUSED ON WINDOWS NT **
  841. DIF_INSTALLINTERFACES - The class installer should create (and/or,
  842. potentially remove) device interfaces for this device information
  843. element.
  844. DIF_DETECTCANCEL - After the detection is stopped, if the class
  845. installer was invoked for DIF_DETECT, then it is invoked for
  846. DIF_DETECTCANCEL. This gives the class installer a chance to clean
  847. up anything it did during DIF_DETECT such as drivers setup to do
  848. detection at reboot, and private data. It is passed the same
  849. HDEVINFO as it was for DIF_DETECT.
  850. DIF_REGISTER_COINSTALLERS - Register device-specific co-installers so
  851. that they can be involved in the rest of the installation.
  852. (DeviceInfoData must be specified.)
  853. DIF_ADDPROPERTYPAGE_ADVANCED - Allows class-/co-installers to supply
  854. advanced property pages for a device.
  855. DIF_ADDPROPERTYPAGE_BASIC - Allows class-/co-installers to supply
  856. basic property pages for a device.
  857. DIF_TROUBLESHOOTER - Allows class-/co-installers to launch a
  858. troubleshooter for this device or to return CHM and HTM
  859. troubleshooter files that will get launched with a call to the
  860. HtmlHelp() API. If the class-/co-installer launches its own
  861. troubleshooter then it should return NO_ERROR, it should return
  862. ERROR_DI_DO_DEFAULT regardless of if it sets the CHM and HTM
  863. values.
  864. DIF_POWERMESSAGEWAKE - Allows class-/co-installers to specify text that
  865. will be displayed on the power tab in device manager. The class-/
  866. co-installer should return NO_ERROR if it specifies any text and
  867. ERROR_DI_DO_DEFAULT otherwise.
  868. DIF_ADDREMOTEPROPERTYPAGE_ADVANCED - Allows class-/co-installers to
  869. supply advanced proerty pages for a device that is on a remote
  870. machine.
  871. DIF_UPDATEDRIVER_UI - Allows a class-/co-installer to display their own
  872. UI when the user presses the update driver button in device
  873. manager. The only real reason to do this is when the default
  874. update driver behavior could cause the device and/or machine not to
  875. work. We don't want IHVs providing their own UI for random reasons.
  876. DIF_INTERFACE_TO_DEVICE - For SWENUM device co-installers, get device
  877. for interface if it's different. Return NO_ERROR if handled
  878. ERROR_DI_DO_DEFAULT otherwise.
  879. (Note: remember to add new DIF_xxxx to pSetupDiDifStrings at start of
  880. file)
  881. DeviceInfoSet - Supplies a handle to the device information set to
  882. perform installation for.
  883. DeviceInfoData - Optionally, specifies a particular device information
  884. element whose class installer is to be called. If this parameter
  885. is not specified, then the class installer for the device information
  886. set itself will be called (if the set has an associated class).
  887. Return Value:
  888. If the function succeeds, the return value is TRUE.
  889. If the function fails, the return value is FALSE. To get extended error
  890. information, call GetLastError.
  891. Remarks:
  892. This function will attempt to load and call the class installer and co-
  893. installers (if any) for the class associated with the device information
  894. element or set specified. If there is no class installer, or the class
  895. installer returns ERR_DI_DO_DEFAULT, then this function will call a default
  896. procedure for the specified class installer function.
  897. --*/
  898. {
  899. DWORD Err;
  900. try {
  901. Err = _SetupDiCallClassInstaller(
  902. InstallFunction,
  903. DeviceInfoSet,
  904. DeviceInfoData,
  905. CALLCI_LOAD_HELPERS | CALLCI_CALL_HELPERS
  906. );
  907. } except(pSetupExceptionFilter(GetExceptionCode())) {
  908. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  909. }
  910. SetLastError(Err);
  911. return (Err == NO_ERROR);
  912. }
  913. DWORD
  914. _SetupDiCallClassInstaller(
  915. IN DI_FUNCTION InstallFunction,
  916. IN HDEVINFO DeviceInfoSet,
  917. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  918. IN DWORD Flags
  919. )
  920. /*++
  921. Routine Description:
  922. Worker routine for SetupDiCallClassInstaller that allows the caller to
  923. control what actions are taken when handling this install request. In
  924. addition to the first three parameters (refer to the documentation for
  925. SetupDiCallClassInstaller for details), the following flags may be
  926. specified in the Flags parameter:
  927. CALLCI_LOAD_HELPERS - If helper modules (class installer, co-installers)
  928. haven't been loaded, load them so they can participate in handling
  929. this install request.
  930. CALLCI_CALL_HELPERS - Call the class installer/co-installers to give them
  931. a chance to handle this install request. If this flag is not
  932. specified, then only the default action will be taken.
  933. CALLCI_ALLOW_DRVSIGN_UI - If an unsigned class installer or co-installer is
  934. encountered, perform standard non-driver signing behavior. (WHQL
  935. doesn't have a certification program for class-/co-installers!)
  936. NTRAID#NTBUG9-166000-2000/08/18-JamieHun -- Driver signing policy for class installers?
  937. (lonnym): We should probably employ driver signing policy
  938. (instead of non-driver signing policy) for class installers of
  939. WHQL-approved classes. However, the user experience here is
  940. problematic (e.g., driver signing popup trying to uninstall an unsigned
  941. driver package).
  942. Return Values:
  943. If this function succeeds, the return value is NO_ERROR. Otherwise, it is
  944. a Win32 error code indicating the cause of failure.
  945. --*/
  946. {
  947. PDEVICE_INFO_SET pDeviceInfoSet;
  948. BOOL MustAbort;
  949. DWORD Err;
  950. PDEVINFO_ELEM DevInfoElem;
  951. PDEVINSTALL_PARAM_BLOCK InstallParamBlock;
  952. HKEY hk;
  953. CONST GUID *ClassGuid;
  954. BOOL bRestoreDiQuietInstall;
  955. BOOL MuteError;
  956. PCOINSTALLER_INTERNAL_CONTEXT CoInstallerInternalContext;
  957. LONG i, CoInstallerCount;
  958. HWND hwndParent;
  959. TCHAR DescBuffer[LINE_LEN];
  960. PTSTR DeviceDesc;
  961. PSETUP_LOG_CONTEXT LogContext;
  962. DWORD slot_dif_code;
  963. BOOL ChangedThreadLogContext;
  964. PSETUP_LOG_CONTEXT SavedLogContext;
  965. DWORD LastErr;
  966. DWORD ErrorLevel;
  967. SPFUSIONINSTANCE spFusionInstance;
  968. VERIFY_CONTEXT VerifyContext;
  969. DWORD slot;
  970. CLASS_INSTALL_PROC ClassInstallerEntryPoint;
  971. HANDLE ClassInstallerFusionContext;
  972. BOOL UnlockDevInfoElem, UnlockDevInfoSet;
  973. ASSERT_HEAP_IS_VALID();
  974. //
  975. // DIF codes must be non-zero...
  976. //
  977. if(!InstallFunction) {
  978. return ERROR_INVALID_PARAMETER;
  979. }
  980. #ifdef _X86_
  981. if(IsWow64) {
  982. //
  983. // This API not allowed in Wow64, class/co installers must/will be
  984. // native
  985. //
  986. return ERROR_IN_WOW64;
  987. }
  988. #endif
  989. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  990. return ERROR_INVALID_HANDLE;
  991. }
  992. //
  993. // Initialize some variables before entering the try/except block...
  994. //
  995. Err = ERROR_DI_DO_DEFAULT;
  996. CoInstallerInternalContext = NULL;
  997. i = 0;
  998. CoInstallerCount = -1; // value indicating count hasn't been retrieved
  999. hk = INVALID_HANDLE_VALUE;
  1000. slot = 0;
  1001. bRestoreDiQuietInstall = FALSE;
  1002. MuteError = FALSE;
  1003. slot_dif_code = 0;
  1004. ChangedThreadLogContext = FALSE;
  1005. SavedLogContext = NULL;
  1006. ErrorLevel = DRIVER_LOG_ERROR;
  1007. UnlockDevInfoElem = UnlockDevInfoSet = FALSE;
  1008. ZeroMemory(&VerifyContext, sizeof(VerifyContext));
  1009. try {
  1010. if(DeviceInfoData) {
  1011. //
  1012. // Then we are to call the class installer for a particular device.
  1013. //
  1014. DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  1015. DeviceInfoData,
  1016. NULL
  1017. );
  1018. if(!DevInfoElem) {
  1019. Err = ERROR_INVALID_PARAMETER;
  1020. leave;
  1021. }
  1022. InstallParamBlock = &(DevInfoElem->InstallParamBlock);
  1023. ClassGuid = &(DevInfoElem->ClassGuid);
  1024. //
  1025. // If the device information element isn't already locked, do so
  1026. // now. That will prevent it from being yanked out from under us
  1027. // when calling a class-/co-installer.
  1028. //
  1029. if(!(DevInfoElem->DiElemFlags & DIE_IS_LOCKED)) {
  1030. DevInfoElem->DiElemFlags |= DIE_IS_LOCKED;
  1031. UnlockDevInfoElem = TRUE;
  1032. }
  1033. } else {
  1034. DevInfoElem = NULL;
  1035. InstallParamBlock = &(pDeviceInfoSet->InstallParamBlock);
  1036. ClassGuid = pDeviceInfoSet->HasClassGuid
  1037. ? &(pDeviceInfoSet->ClassGuid)
  1038. : NULL;
  1039. //
  1040. // We don't have a device information element to lock, so we'll
  1041. // lock the set itself...
  1042. //
  1043. if(!(pDeviceInfoSet->DiSetFlags & DISET_IS_LOCKED)) {
  1044. pDeviceInfoSet->DiSetFlags |= DISET_IS_LOCKED;
  1045. UnlockDevInfoSet = TRUE;
  1046. }
  1047. }
  1048. //
  1049. // Set the local log context before it gets used.
  1050. //
  1051. LogContext = InstallParamBlock->LogContext;
  1052. //
  1053. // If we are processing DIF_ALLOW_INSTALL then we need to make sure
  1054. // that the DI_QUIETINSTALL flag is only set if we are doing a non-
  1055. // interactive (server-side) install or we are in GUI mode setup. In
  1056. // any other case we need to remove the DI_QUIETINSTALL flag otherwise
  1057. // class installers might think they can't display any UI and fail the
  1058. // DIF_ALLOW_INSTALL.
  1059. //
  1060. if((InstallFunction == DIF_ALLOW_INSTALL) &&
  1061. (InstallParamBlock->Flags & DI_QUIETINSTALL) &&
  1062. !(InstallParamBlock->FlagsEx & DI_FLAGSEX_IN_SYSTEM_SETUP) &&
  1063. !(GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP))) {
  1064. InstallParamBlock->Flags &= ~DI_QUIETINSTALL;
  1065. bRestoreDiQuietInstall = TRUE;
  1066. }
  1067. if(Flags & CALLCI_LOAD_HELPERS) {
  1068. //
  1069. // Retrieve the parent window handle, as we may need it below if we
  1070. // need to popup UI due to unsigned class-/co-installers.
  1071. //
  1072. if(hwndParent = InstallParamBlock->hwndParent) {
  1073. if(!IsWindow(hwndParent)) {
  1074. hwndParent = NULL;
  1075. }
  1076. }
  1077. //
  1078. // Retrieve a device description to use in case we need to give a
  1079. // driver signing warn/block popup.
  1080. //
  1081. if(GetBestDeviceDesc(DeviceInfoSet, DeviceInfoData, DescBuffer)) {
  1082. DeviceDesc = DescBuffer;
  1083. } else {
  1084. DeviceDesc = NULL;
  1085. }
  1086. //
  1087. // If the class installer has not been loaded, then load it and
  1088. // get the function address for the ClassInstall function.
  1089. //
  1090. if(!InstallParamBlock->hinstClassInstaller) {
  1091. if(ClassGuid &&
  1092. (hk = SetupDiOpenClassRegKey(ClassGuid, KEY_READ)) != INVALID_HANDLE_VALUE) {
  1093. slot = AllocLogInfoSlot(LogContext, FALSE);
  1094. WriteLogEntry(LogContext,
  1095. slot,
  1096. MSG_LOG_CI_MODULE,
  1097. NULL,
  1098. DeviceDesc ? DeviceDesc : TEXT("")
  1099. );
  1100. try {
  1101. Err = GetModuleEntryPoint(hk,
  1102. pszInstaller32,
  1103. pszCiDefaultProc,
  1104. &(InstallParamBlock->hinstClassInstaller),
  1105. &((FARPROC)InstallParamBlock->ClassInstallerEntryPoint),
  1106. &(InstallParamBlock->ClassInstallerFusionContext),
  1107. &MustAbort,
  1108. LogContext,
  1109. hwndParent,
  1110. ClassGuid,
  1111. SetupapiVerifyClassInstProblem,
  1112. DeviceDesc,
  1113. DRIVERSIGN_NONE,
  1114. TRUE,
  1115. &VerifyContext
  1116. );
  1117. } except(pSetupExceptionFilter(GetExceptionCode())) {
  1118. pSetupExceptionHandler(GetExceptionCode(),
  1119. ERROR_INVALID_CLASS_INSTALLER,
  1120. &Err
  1121. );
  1122. InstallParamBlock->ClassInstallerEntryPoint = NULL;
  1123. }
  1124. if(slot) {
  1125. ReleaseLogInfoSlot(LogContext, slot);
  1126. slot = 0;
  1127. }
  1128. RegCloseKey(hk);
  1129. hk = INVALID_HANDLE_VALUE;
  1130. if((Err != NO_ERROR) && (Err != ERROR_DI_DO_DEFAULT)) {
  1131. if(!(InstallParamBlock->FlagsEx & DI_FLAGSEX_CI_FAILED)) {
  1132. TCHAR ClassName[MAX_GUID_STRING_LEN];
  1133. TCHAR Title[MAX_TITLE_LEN];
  1134. if(!SetupDiClassNameFromGuid(ClassGuid,
  1135. ClassName,
  1136. SIZECHARS(ClassName),
  1137. NULL)) {
  1138. //
  1139. // Use the ClassName buffer to hold the class
  1140. // GUID string (it's better than nothin')
  1141. //
  1142. pSetupStringFromGuid(ClassGuid,
  1143. ClassName,
  1144. SIZECHARS(ClassName)
  1145. );
  1146. }
  1147. //
  1148. // Write out an event log entry about this.
  1149. //
  1150. WriteLogEntry(LogContext,
  1151. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  1152. MSG_CI_LOADFAIL_ERROR,
  1153. NULL,
  1154. ClassName
  1155. );
  1156. WriteLogError(LogContext, DRIVER_LOG_ERROR, Err);
  1157. MuteError = TRUE;
  1158. if(!(GlobalSetupFlags &
  1159. (PSPGF_NONINTERACTIVE | PSPGF_UNATTENDED_SETUP))) {
  1160. if(!LoadString(MyDllModuleHandle,
  1161. IDS_DEVICEINSTALLER,
  1162. Title,
  1163. SIZECHARS(Title))) {
  1164. *Title = TEXT('\0');
  1165. }
  1166. FormatMessageBox(MyDllModuleHandle,
  1167. InstallParamBlock->hwndParent,
  1168. MSG_CI_LOADFAIL_ERROR,
  1169. Title,
  1170. MB_OK,
  1171. ClassName
  1172. );
  1173. }
  1174. InstallParamBlock->FlagsEx |= DI_FLAGSEX_CI_FAILED;
  1175. }
  1176. Err = ERROR_INVALID_CLASS_INSTALLER;
  1177. leave;
  1178. }
  1179. }
  1180. }
  1181. //
  1182. // If we haven't retrieved a list of co-installers to call,
  1183. // retrieve the list now.
  1184. //
  1185. if(InstallParamBlock->CoInstallerCount == -1) {
  1186. slot = AllocLogInfoSlot(LogContext, FALSE);
  1187. WriteLogEntry(LogContext,
  1188. slot,
  1189. MSG_LOG_COINST_MODULE,
  1190. NULL,
  1191. DeviceDesc
  1192. );
  1193. Err = pSetupDiGetCoInstallerList(DeviceInfoSet,
  1194. DeviceInfoData,
  1195. ClassGuid,
  1196. InstallParamBlock,
  1197. &VerifyContext
  1198. );
  1199. if(slot) {
  1200. ReleaseLogInfoSlot(LogContext, slot);
  1201. slot = 0;
  1202. }
  1203. if(Err != NO_ERROR) {
  1204. leave;
  1205. }
  1206. MYASSERT(InstallParamBlock->CoInstallerCount >= 0);
  1207. }
  1208. }
  1209. slot_dif_code = AllocLogInfoSlotOrLevel(LogContext,
  1210. DRIVER_LOG_VERBOSE1,
  1211. FALSE
  1212. );
  1213. if(slot_dif_code) {
  1214. //
  1215. // this is skipped if we know we would never log anything
  1216. //
  1217. // pass a string which we may log with an error or will log at
  1218. // VERBOSE1 level
  1219. //
  1220. if(InstallFunction >= (sizeof(pSetupDiDifStrings)/sizeof(pSetupDiDifStrings[0]))) {
  1221. //
  1222. // This is a user-defined DIF code...
  1223. //
  1224. WriteLogEntry(LogContext,
  1225. slot_dif_code,
  1226. MSG_LOG_DI_UNUSED_FUNC,
  1227. NULL,
  1228. InstallFunction
  1229. );
  1230. } else {
  1231. //
  1232. // use the string version of the DIF code
  1233. //
  1234. WriteLogEntry(LogContext,
  1235. slot_dif_code,
  1236. MSG_LOG_DI_FUNC,
  1237. NULL,
  1238. pSetupDiDifStrings[InstallFunction]
  1239. );
  1240. }
  1241. }
  1242. //
  1243. // do any pre DIF cleanup
  1244. //
  1245. switch(InstallFunction) {
  1246. case DIF_REGISTER_COINSTALLERS:
  1247. //
  1248. // NTRAID#NTBUG9-644874-2002/06/17-lonnym -- DIF_REGISTER_COINSTALLERS is destructive upon error
  1249. //
  1250. hk = SetupDiOpenDevRegKey(DeviceInfoSet,
  1251. DeviceInfoData,
  1252. DICS_FLAG_GLOBAL,
  1253. 0,
  1254. DIREG_DRV,
  1255. KEY_WRITE
  1256. );
  1257. if(hk != INVALID_HANDLE_VALUE) {
  1258. //
  1259. // Clean up device SW key:
  1260. //
  1261. // remove CoInstallers32 - can introduce unwanted
  1262. // co-installers
  1263. //
  1264. // remove EnumPropPages32 - can introduce unwanted
  1265. // property pages
  1266. //
  1267. RegDeleteValue(hk, pszCoInstallers32);
  1268. RegDeleteValue(hk, pszEnumPropPages32);
  1269. RegCloseKey(hk);
  1270. hk = INVALID_HANDLE_VALUE;
  1271. }
  1272. break;
  1273. case DIF_INSTALLDEVICE:
  1274. //
  1275. // NTRAID#NTBUG9-644997-2002/06/17-lonnym -- DIF_INSTALLDEVICE is destructive upon error
  1276. //
  1277. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1278. DeviceInfoData,
  1279. SPDRP_UPPERFILTERS,
  1280. NULL,
  1281. 0
  1282. );
  1283. SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
  1284. DeviceInfoData,
  1285. SPDRP_LOWERFILTERS,
  1286. NULL,
  1287. 0
  1288. );
  1289. break;
  1290. default:
  1291. break;
  1292. }
  1293. if(Flags & CALLCI_CALL_HELPERS) {
  1294. //
  1295. // Push log context as thread's default. This will cause orphaned
  1296. // log sections to be merged.
  1297. //
  1298. ChangedThreadLogContext = SetThreadLogContext(LogContext,
  1299. &SavedLogContext
  1300. );
  1301. if(ChangedThreadLogContext) {
  1302. //
  1303. // Add one more ref to protect log context against thread
  1304. // freeing DeviceInfoSet.
  1305. //
  1306. RefLogContext(LogContext);
  1307. }
  1308. //
  1309. // Before we go and try to call any co-installers, first remember
  1310. // the class installer entry point and fusion context, because
  1311. // we'll need it below, and we don't want to wait until the devinfo
  1312. // set has already been unlocked before retrieving this
  1313. // information.
  1314. //
  1315. ClassInstallerEntryPoint =
  1316. InstallParamBlock->ClassInstallerEntryPoint;
  1317. ClassInstallerFusionContext =
  1318. InstallParamBlock->ClassInstallerFusionContext;
  1319. //
  1320. // Store the co-installer count in a local variable for later use.
  1321. // We don't trust accessing it from the install parameter block
  1322. // because after we release the lock (prior to calling the
  1323. // co-installers), the device information element could get deleted
  1324. // out from under us!
  1325. //
  1326. CoInstallerCount = InstallParamBlock->CoInstallerCount;
  1327. //
  1328. // Note: CoInstallerCount may still be -1 here, because we may
  1329. // have been asked to only call previously-loaded helper modules,
  1330. // and not load any new ones (e.g., if we're simply going to call
  1331. // them to do clean-up in preparation for unload).
  1332. //
  1333. if(CoInstallerCount > 0) {
  1334. //
  1335. // Allocate an array of co-installer context structures to be
  1336. // used when calling (and potentially, re-calling) the entry
  1337. // points.
  1338. //
  1339. CoInstallerInternalContext = MyMalloc(sizeof(COINSTALLER_INTERNAL_CONTEXT) * CoInstallerCount);
  1340. if(!CoInstallerInternalContext) {
  1341. Err = ERROR_NOT_ENOUGH_MEMORY;
  1342. leave;
  1343. }
  1344. ZeroMemory(CoInstallerInternalContext,
  1345. sizeof(COINSTALLER_INTERNAL_CONTEXT) * CoInstallerCount
  1346. );
  1347. //
  1348. // Loop through our list of co-installers, storing the
  1349. // necessary information about each one into our context list.
  1350. // We must do this because we've no guarantee that the list of
  1351. // co-installers won't change as a result of processing this
  1352. // DIF request. (We do, however, know that the set/element
  1353. // won't be yanked out from under us, since we locked these
  1354. // down.)
  1355. //
  1356. for(i = 0; i < CoInstallerCount; i++) {
  1357. CoInstallerInternalContext[i].CoInstallerEntryPoint =
  1358. InstallParamBlock->CoInstallerList[i].CoInstallerEntryPoint;
  1359. CoInstallerInternalContext[i].CoInstallerFusionContext =
  1360. InstallParamBlock->CoInstallerList[i].CoInstallerFusionContext;
  1361. }
  1362. //
  1363. // Call each co-installer. We must unlock the devinfo set
  1364. // first, to avoid deadlocks.
  1365. //
  1366. UnlockDeviceInfoSet(pDeviceInfoSet);
  1367. pDeviceInfoSet = NULL;
  1368. for(i = 0; i < CoInstallerCount; i++) {
  1369. WriteLogEntry(LogContext,
  1370. DRIVER_LOG_TIME,
  1371. MSG_LOG_COINST_START,
  1372. NULL,
  1373. i + 1,
  1374. CoInstallerCount
  1375. );
  1376. spFusionEnterContext(
  1377. CoInstallerInternalContext[i].CoInstallerFusionContext,
  1378. &spFusionInstance
  1379. );
  1380. try {
  1381. Err = CoInstallerInternalContext[i].CoInstallerEntryPoint(
  1382. InstallFunction,
  1383. DeviceInfoSet,
  1384. DeviceInfoData,
  1385. &(CoInstallerInternalContext[i].Context)
  1386. );
  1387. } finally {
  1388. spFusionLeaveContext(&spFusionInstance);
  1389. }
  1390. ASSERT_HEAP_IS_VALID();
  1391. if((Err != NO_ERROR) && (Err != ERROR_DI_POSTPROCESSING_REQUIRED)) {
  1392. ErrorLevel = FilterLevelOnInstallerError(ErrorLevel,
  1393. Err
  1394. );
  1395. WriteLogEntry(LogContext,
  1396. ErrorLevel | SETUP_LOG_BUFFER,
  1397. MSG_LOG_COINST_END_ERROR,
  1398. NULL,
  1399. i + 1,
  1400. CoInstallerCount
  1401. );
  1402. WriteLogError(LogContext, ErrorLevel, Err);
  1403. MuteError = TRUE; // already logged it
  1404. leave;
  1405. } else {
  1406. WriteLogEntry(LogContext,
  1407. DRIVER_LOG_VERBOSE1,
  1408. MSG_LOG_COINST_END,
  1409. NULL,
  1410. i + 1,
  1411. CoInstallerCount
  1412. );
  1413. if(Err == ERROR_DI_POSTPROCESSING_REQUIRED) {
  1414. CoInstallerInternalContext[i].DoPostProcessing = TRUE;
  1415. }
  1416. }
  1417. }
  1418. }
  1419. //
  1420. // If there is a class installer entry point, then call it.
  1421. //
  1422. if(ClassInstallerEntryPoint) {
  1423. //
  1424. // Make sure we don't have the HDEVINFO locked.
  1425. //
  1426. if(pDeviceInfoSet) {
  1427. UnlockDeviceInfoSet(pDeviceInfoSet);
  1428. pDeviceInfoSet = NULL;
  1429. }
  1430. WriteLogEntry(LogContext,
  1431. DRIVER_LOG_TIME,
  1432. MSG_LOG_CI_START,
  1433. NULL
  1434. );
  1435. spFusionEnterContext(ClassInstallerFusionContext,
  1436. &spFusionInstance
  1437. );
  1438. try {
  1439. Err = ClassInstallerEntryPoint(InstallFunction,
  1440. DeviceInfoSet,
  1441. DeviceInfoData
  1442. );
  1443. } finally {
  1444. spFusionLeaveContext(&spFusionInstance);
  1445. }
  1446. ASSERT_HEAP_IS_VALID();
  1447. if((Err != NO_ERROR) && (Err != ERROR_DI_DO_DEFAULT)) {
  1448. ErrorLevel = FilterLevelOnInstallerError(ErrorLevel, Err);
  1449. WriteLogEntry(LogContext,
  1450. ErrorLevel | SETUP_LOG_BUFFER,
  1451. MSG_LOG_CI_END_ERROR,
  1452. NULL
  1453. );
  1454. WriteLogError(LogContext, ErrorLevel, Err);
  1455. MuteError = TRUE; // already logged it
  1456. } else {
  1457. WriteLogEntry(LogContext,
  1458. DRIVER_LOG_VERBOSE1,
  1459. MSG_LOG_CI_END,
  1460. NULL
  1461. );
  1462. }
  1463. if(Err != ERROR_DI_DO_DEFAULT) {
  1464. //
  1465. // class installer handled
  1466. //
  1467. leave;
  1468. }
  1469. } else {
  1470. Err = ERROR_DI_DO_DEFAULT;
  1471. }
  1472. }
  1473. if(InstallParamBlock->Flags & DI_NODI_DEFAULTACTION) {
  1474. //
  1475. // We shouldn't provide a default action--just return the class
  1476. // installer result.
  1477. //
  1478. leave;
  1479. }
  1480. Err = NO_ERROR;
  1481. //
  1482. // Make sure the devinfo set is unlocked before calling the appropriate
  1483. // default handler routine...
  1484. //
  1485. if(pDeviceInfoSet) {
  1486. UnlockDeviceInfoSet(pDeviceInfoSet);
  1487. pDeviceInfoSet = NULL;
  1488. }
  1489. WriteLogEntry(LogContext,
  1490. DRIVER_LOG_VERBOSE1,
  1491. MSG_LOG_CI_DEF_START,
  1492. NULL
  1493. );
  1494. switch(InstallFunction) {
  1495. case DIF_SELECTDEVICE :
  1496. Err = GLE_FN_CALL(FALSE,
  1497. SetupDiSelectDevice(DeviceInfoSet,
  1498. DeviceInfoData)
  1499. );
  1500. break;
  1501. case DIF_SELECTBESTCOMPATDRV :
  1502. Err = GLE_FN_CALL(FALSE,
  1503. SetupDiSelectBestCompatDrv(DeviceInfoSet,
  1504. DeviceInfoData)
  1505. );
  1506. if(Err == ERROR_NO_COMPAT_DRIVERS) {
  1507. ErrorLevel = DRIVER_LOG_WARNING;
  1508. }
  1509. break;
  1510. case DIF_INSTALLDEVICE :
  1511. Err = GLE_FN_CALL(FALSE,
  1512. SetupDiInstallDevice(DeviceInfoSet,
  1513. DeviceInfoData)
  1514. );
  1515. break;
  1516. case DIF_INSTALLDEVICEFILES :
  1517. Err = GLE_FN_CALL(FALSE,
  1518. SetupDiInstallDriverFiles(DeviceInfoSet,
  1519. DeviceInfoData)
  1520. );
  1521. break;
  1522. case DIF_INSTALLINTERFACES :
  1523. Err = GLE_FN_CALL(FALSE,
  1524. SetupDiInstallDeviceInterfaces(
  1525. DeviceInfoSet,
  1526. DeviceInfoData)
  1527. );
  1528. break;
  1529. case DIF_REGISTER_COINSTALLERS :
  1530. Err = GLE_FN_CALL(FALSE,
  1531. SetupDiRegisterCoDeviceInstallers(
  1532. DeviceInfoSet,
  1533. DeviceInfoData)
  1534. );
  1535. break;
  1536. case DIF_REMOVE :
  1537. Err = GLE_FN_CALL(FALSE,
  1538. SetupDiRemoveDevice(DeviceInfoSet,
  1539. DeviceInfoData)
  1540. );
  1541. break;
  1542. case DIF_UNREMOVE :
  1543. Err = GLE_FN_CALL(FALSE,
  1544. SetupDiUnremoveDevice(DeviceInfoSet,
  1545. DeviceInfoData)
  1546. );
  1547. break;
  1548. case DIF_MOVEDEVICE :
  1549. //
  1550. // This device install action has been deprecated.
  1551. //
  1552. Err = ERROR_DI_FUNCTION_OBSOLETE;
  1553. break;
  1554. case DIF_PROPERTYCHANGE :
  1555. Err = GLE_FN_CALL(FALSE,
  1556. SetupDiChangeState(DeviceInfoSet,
  1557. DeviceInfoData)
  1558. );
  1559. break;
  1560. case DIF_REGISTERDEVICE :
  1561. Err = GLE_FN_CALL(FALSE,
  1562. SetupDiRegisterDeviceInfo(DeviceInfoSet,
  1563. DeviceInfoData,
  1564. 0,
  1565. NULL,
  1566. NULL,
  1567. NULL)
  1568. );
  1569. break;
  1570. //
  1571. // FUTURE-2002/06/18-lonnym -- End-of-life old Win9x netdi DIF codes
  1572. //
  1573. // These are Win9x messages for class installers such as the
  1574. // Network, where the class installer will do all of the work. If
  1575. // no action is taken, ie, the class installer returns
  1576. // ERROR_DI_DO_DEFAULT, then we return OK, since there is no
  1577. // default action for these cases.
  1578. //
  1579. case DIF_SELECTCLASSDRIVERS:
  1580. case DIF_VALIDATECLASSDRIVERS:
  1581. case DIF_INSTALLCLASSDRIVERS:
  1582. //
  1583. // Let fall through to default handling...
  1584. //
  1585. default :
  1586. //
  1587. // If the DIF request didn't have a default handler, then let
  1588. // the caller deal with it...
  1589. //
  1590. Err = ERROR_DI_DO_DEFAULT;
  1591. break;
  1592. }
  1593. if(!MuteError) {
  1594. if((Err != NO_ERROR) && (Err != ERROR_DI_DO_DEFAULT)) {
  1595. ErrorLevel = FilterLevelOnInstallerError(ErrorLevel, Err);
  1596. WriteLogEntry(LogContext,
  1597. ErrorLevel | SETUP_LOG_BUFFER,
  1598. MSG_LOG_CI_DEF_END_ERROR,
  1599. NULL
  1600. );
  1601. WriteLogError(LogContext, ErrorLevel, Err);
  1602. MuteError = TRUE; // already logged it
  1603. } else {
  1604. WriteLogEntry(LogContext,
  1605. DRIVER_LOG_VERBOSE1,
  1606. MSG_LOG_CI_DEF_END,
  1607. NULL
  1608. );
  1609. }
  1610. }
  1611. } except(pSetupExceptionFilter(GetExceptionCode())) {
  1612. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  1613. }
  1614. if(hk != INVALID_HANDLE_VALUE) {
  1615. RegCloseKey(hk);
  1616. }
  1617. if(slot) {
  1618. ReleaseLogInfoSlot(LogContext, slot);
  1619. }
  1620. //
  1621. // Free any context handles that may have been allocated while verifying/
  1622. // loading the class installer and co-installers.
  1623. //
  1624. pSetupFreeVerifyContextMembers(&VerifyContext);
  1625. ASSERT_HEAP_IS_VALID();
  1626. //
  1627. // Do a post-processing callback to any of the co-installers that requested
  1628. // one.
  1629. //
  1630. for(i--; i >= 0; i--) {
  1631. if(CoInstallerInternalContext[i].DoPostProcessing) {
  1632. //
  1633. // If we get to here, the HDEVINFO shouldn't be locked...
  1634. //
  1635. MYASSERT(!pDeviceInfoSet);
  1636. CoInstallerInternalContext[i].Context.PostProcessing = TRUE;
  1637. CoInstallerInternalContext[i].Context.InstallResult = Err;
  1638. LastErr = Err;
  1639. try {
  1640. WriteLogEntry(LogContext,
  1641. DRIVER_LOG_TIME,
  1642. MSG_LOG_COINST_POST_START,
  1643. NULL,
  1644. i + 1
  1645. );
  1646. spFusionEnterContext(
  1647. CoInstallerInternalContext[i].CoInstallerFusionContext,
  1648. &spFusionInstance
  1649. );
  1650. try {
  1651. Err = CoInstallerInternalContext[i].CoInstallerEntryPoint(
  1652. InstallFunction,
  1653. DeviceInfoSet,
  1654. DevInfoElem ? DeviceInfoData : NULL,
  1655. &(CoInstallerInternalContext[i].Context)
  1656. );
  1657. } finally {
  1658. spFusionLeaveContext(&spFusionInstance);
  1659. }
  1660. ASSERT_HEAP_IS_VALID();
  1661. if((Err != LastErr) &&
  1662. ((LastErr != ERROR_DI_DO_DEFAULT) || (Err != NO_ERROR))) {
  1663. //
  1664. // If error status has changed (even to success)
  1665. // log this as an error
  1666. //
  1667. if(((LastErr == NO_ERROR) || (LastErr == ERROR_DI_DO_DEFAULT))
  1668. && (Err != NO_ERROR) && (Err != ERROR_DI_DO_DEFAULT)) {
  1669. WriteLogEntry(
  1670. LogContext,
  1671. ErrorLevel | SETUP_LOG_BUFFER,
  1672. MSG_LOG_COINST_POST_END_ERROR,
  1673. NULL,
  1674. i+1);
  1675. WriteLogError(LogContext, ErrorLevel, Err);
  1676. } else {
  1677. WriteLogEntry(
  1678. LogContext,
  1679. DRIVER_LOG_WARNING | SETUP_LOG_BUFFER,
  1680. MSG_LOG_COINST_POST_CHANGE_ERROR,
  1681. NULL,
  1682. i+1);
  1683. WriteLogError(LogContext, DRIVER_LOG_WARNING, Err);
  1684. }
  1685. } else {
  1686. WriteLogEntry(
  1687. LogContext,
  1688. DRIVER_LOG_VERBOSE1,
  1689. MSG_LOG_COINST_POST_END,
  1690. NULL,
  1691. i+1);
  1692. }
  1693. } except(pSetupExceptionFilter(GetExceptionCode())) {
  1694. pSetupExceptionHandler(GetExceptionCode(),
  1695. ERROR_INVALID_PARAMETER,
  1696. NULL
  1697. );
  1698. //
  1699. // Ignore any co-installer that generates an exception during
  1700. // post-processing.
  1701. //
  1702. }
  1703. }
  1704. }
  1705. //
  1706. // If we need to restore any state on the devinfo set or element, do that
  1707. // now (we may need to re-acquire the lock before doing so)...
  1708. //
  1709. if(bRestoreDiQuietInstall
  1710. || UnlockDevInfoElem
  1711. || UnlockDevInfoSet) {
  1712. if(!pDeviceInfoSet) {
  1713. pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet);
  1714. //
  1715. // Since we had the set/element "pinned", we should've been able to
  1716. // re-acquire the lock...
  1717. //
  1718. MYASSERT(pDeviceInfoSet);
  1719. }
  1720. try {
  1721. //
  1722. // Since we had the set/element "pinned", then our devinfo element,
  1723. // and the pointer to the install parameter block should be the
  1724. // same...
  1725. //
  1726. #if ASSERTS_ON
  1727. if(DevInfoElem) {
  1728. MYASSERT(DevInfoElem == FindAssociatedDevInfoElem(
  1729. pDeviceInfoSet,
  1730. DeviceInfoData,
  1731. NULL));
  1732. MYASSERT(InstallParamBlock == &(DevInfoElem->InstallParamBlock));
  1733. } else {
  1734. MYASSERT(InstallParamBlock == &(pDeviceInfoSet->InstallParamBlock));
  1735. }
  1736. #endif
  1737. if(UnlockDevInfoElem) {
  1738. MYASSERT(DevInfoElem);
  1739. MYASSERT(DevInfoElem->DiElemFlags & DIE_IS_LOCKED);
  1740. DevInfoElem->DiElemFlags &= ~DIE_IS_LOCKED;
  1741. } else if(UnlockDevInfoSet) {
  1742. MYASSERT(pDeviceInfoSet->DiSetFlags & DISET_IS_LOCKED);
  1743. pDeviceInfoSet->DiSetFlags &= ~DISET_IS_LOCKED;
  1744. }
  1745. if(bRestoreDiQuietInstall) {
  1746. InstallParamBlock->Flags |= DI_QUIETINSTALL;
  1747. }
  1748. } except(pSetupExceptionFilter(GetExceptionCode())) {
  1749. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, NULL);
  1750. }
  1751. }
  1752. if(pDeviceInfoSet) {
  1753. UnlockDeviceInfoSet(pDeviceInfoSet);
  1754. }
  1755. if(CoInstallerInternalContext) {
  1756. MyFree(CoInstallerInternalContext);
  1757. }
  1758. //
  1759. // If we just did a DIF_REGISTER_COINSTALLERS, then we invalidated our
  1760. // current list of co-installers. Clear our list, so it will be retrieved
  1761. // next time. (NOTE: Normally, the default action will be taken (i.e.,
  1762. // SetupDiRegisterCoDeviceInstallers), which will have already invalidated
  1763. // the list. The class installer may have handled this themselves,
  1764. // however, so we'll invalidate the list here as well just to be safe.)
  1765. //
  1766. if(InstallFunction == DIF_REGISTER_COINSTALLERS) {
  1767. InvalidateHelperModules(DeviceInfoSet, DeviceInfoData, IHM_COINSTALLERS_ONLY);
  1768. }
  1769. if(!MuteError && (Err != NO_ERROR) && (Err != ERROR_DI_DO_DEFAULT)) {
  1770. ErrorLevel = FilterLevelOnInstallerError(ErrorLevel, Err);
  1771. WriteLogEntry(LogContext,
  1772. ErrorLevel | SETUP_LOG_BUFFER,
  1773. MSG_LOG_CCI_ERROR,
  1774. NULL,
  1775. i + 1
  1776. );
  1777. WriteLogError(LogContext, ErrorLevel, Err);
  1778. }
  1779. if(slot_dif_code) {
  1780. ReleaseLogInfoSlot(LogContext, slot_dif_code);
  1781. }
  1782. if(ChangedThreadLogContext) {
  1783. //
  1784. // restore thread log context
  1785. //
  1786. SetThreadLogContext(SavedLogContext, NULL);
  1787. DeleteLogContext(LogContext); // counter RefLogContext
  1788. }
  1789. return Err;
  1790. }
  1791. //
  1792. // ANSI version
  1793. //
  1794. BOOL
  1795. WINAPI
  1796. SetupDiInstallClassExA(
  1797. IN HWND hwndParent, OPTIONAL
  1798. IN PCSTR InfFileName, OPTIONAL
  1799. IN DWORD Flags,
  1800. IN HSPFILEQ FileQueue, OPTIONAL
  1801. IN CONST GUID *InterfaceClassGuid, OPTIONAL
  1802. IN PVOID Reserved1,
  1803. IN PVOID Reserved2
  1804. )
  1805. {
  1806. PCWSTR UnicodeInfFileName = NULL;
  1807. DWORD rc;
  1808. try {
  1809. if(InfFileName) {
  1810. rc = pSetupCaptureAndConvertAnsiArg(InfFileName,
  1811. &UnicodeInfFileName
  1812. );
  1813. if(rc != NO_ERROR) {
  1814. leave;
  1815. }
  1816. }
  1817. rc = GLE_FN_CALL(FALSE,
  1818. SetupDiInstallClassExW(hwndParent,
  1819. UnicodeInfFileName,
  1820. Flags,
  1821. FileQueue,
  1822. InterfaceClassGuid,
  1823. Reserved1,
  1824. Reserved2)
  1825. );
  1826. } except(pSetupExceptionFilter(GetExceptionCode())) {
  1827. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  1828. }
  1829. if(UnicodeInfFileName) {
  1830. MyFree(UnicodeInfFileName);
  1831. }
  1832. SetLastError(rc);
  1833. return (rc == NO_ERROR);
  1834. }
  1835. BOOL
  1836. WINAPI
  1837. SetupDiInstallClassEx(
  1838. IN HWND hwndParent, OPTIONAL
  1839. IN PCTSTR InfFileName, OPTIONAL
  1840. IN DWORD Flags,
  1841. IN HSPFILEQ FileQueue, OPTIONAL
  1842. IN CONST GUID *InterfaceClassGuid, OPTIONAL
  1843. IN PVOID Reserved1,
  1844. IN PVOID Reserved2
  1845. )
  1846. /*++
  1847. Routine Description:
  1848. This routine either:
  1849. a) Installs a class installer by running the [ClassInstall32] section
  1850. of the specified INF, or
  1851. b) Installs an interface class specified in the InterfaceClassGuid
  1852. parameter, running the install section for this class as listed in
  1853. the [InterfaceInstall32] of the specified INF (if there is no entry,
  1854. then installation simply involves creating the interface class
  1855. subkey under the DeviceClasses key.
  1856. If the InterfaceClassGuid parameter is specified, then we're installing an
  1857. interface class (case b), otherwise, we're installing a class installer
  1858. (case a).
  1859. Arguments:
  1860. hwndParent - Optionally, supplies the handle of the parent window for any
  1861. UI brought up as a result of installing this class.
  1862. InfFileName - Optionally, supplies the name of the INF file containing a
  1863. [ClassInstall32] section (if we're installing a class installer), or
  1864. an [InterfaceInstall32] section with an entry for the specified
  1865. interface class (if we're installing an interface class). If
  1866. installing a class installer, this parameter _must_ be supplied.
  1867. Flags - Flags that control the installation. May be a combination of the
  1868. following:
  1869. DI_NOVCP - This flag should be specified if HSPFILEQ is supplied. This
  1870. instructs SetupInstallFromInfSection to not create a queue of its
  1871. own, and instead to use the caller-supplied one. If this flag is
  1872. specified, then no file copying will be done.
  1873. DI_NOBROWSE - This flag should be specified if no file browsing should
  1874. be allowed in the event a copy operation cannot find a specified
  1875. file. If the user supplies their own file queue, then this flag is
  1876. ignored.
  1877. DI_FORCECOPY - This flag should be specified if the files should always
  1878. be copied, even if they're already present on the user's machine
  1879. (i.e., don't ask the user if they want to keep their existing
  1880. files). If the user supplies their own file queue, then this flag
  1881. is ignored.
  1882. DI_QUIETINSTALL - This flag should be specified if UI should be
  1883. suppressed unless absolutely necessary (i.e., no progress dialog).
  1884. If the user supplies their own queue, then this flag is ignored.
  1885. (NOTE: During GUI-mode setup on Windows NT, quiet-install behavior
  1886. is always employed in the absence of a user-supplied file queue.)
  1887. FileQueue - If the DI_NOVCP flag is specified, then this parameter supplies
  1888. a handle to a file queue where file operations are to be queued (but
  1889. not committed).
  1890. InterfaceClassGuid - Optionally, specifies the interface class to be
  1891. installed. If this parameter is not specified, then we are installing
  1892. a class installer whose class is the class of the INF specified by
  1893. InfFileName.
  1894. Reserved1, Reserved2 - Reserved for future use. Must be NULL.
  1895. Return Value:
  1896. If the function succeeds, the return value is TRUE.
  1897. If the function fails, the return value is FALSE. To get extended error
  1898. information, call GetLastError.
  1899. Remarks:
  1900. This API is generally called by the "New Hardware Found" process when it
  1901. installs a device of a new device setup class.
  1902. Class installers may also use this API to install new interface classes.
  1903. Note that interface class installation can also happen automatically as a
  1904. result of installing device interfaces for a device instance (via
  1905. SetupDiInstallDeviceInterfaces).
  1906. --*/
  1907. {
  1908. HINF hInf = INVALID_HANDLE_VALUE;
  1909. DWORD Err, ScanQueueResult;
  1910. TCHAR ClassInstallSectionName[MAX_SECT_NAME_LEN];
  1911. DWORD ClassInstallSectionNameLen;
  1912. GUID ClassGuid;
  1913. BOOL ClassGuidIsValid = FALSE;
  1914. TCHAR ClassGuidStringBuffer[GUID_STRING_LEN];
  1915. HKEY hKey = INVALID_HANDLE_VALUE;
  1916. PSP_FILE_CALLBACK MsgHandler;
  1917. PVOID MsgHandlerContext = NULL;
  1918. BOOL KeyNewlyCreated = FALSE;
  1919. PCTSTR ClassName;
  1920. BOOL CloseFileQueue = FALSE;
  1921. PTSTR SectionExtension;
  1922. INFCONTEXT InterfaceClassInstallLine;
  1923. PCTSTR UndecoratedInstallSection;
  1924. DWORD InstallFlags;
  1925. REGMOD_CONTEXT RegContext;
  1926. BOOL NoProgressUI;
  1927. PSETUP_LOG_CONTEXT LogContext = NULL;
  1928. TCHAR szNewName[MAX_PATH];
  1929. BOOL OemInfFileToCopy = FALSE;
  1930. BOOL NullDriverInstall;
  1931. HRESULT hr;
  1932. try {
  1933. //
  1934. // Validate the flags.
  1935. //
  1936. if(Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL)) {
  1937. Err = ERROR_INVALID_FLAGS;
  1938. leave;
  1939. }
  1940. //
  1941. // If the caller didn't specify an interface class GUID (i.e., we're
  1942. // installing a class installer), then they'd better have supplied us
  1943. // with an INF filename. Also, they have to pass NULL for the Reserved
  1944. // arguments.
  1945. //
  1946. if((!InterfaceClassGuid && !InfFileName) || Reserved1 || Reserved2) {
  1947. Err = ERROR_INVALID_PARAMETER;
  1948. leave;
  1949. }
  1950. //
  1951. // Make sure that the caller supplied us with a file queue, if
  1952. // necessary.
  1953. //
  1954. if((Flags & DI_NOVCP) && (!FileQueue || (FileQueue == INVALID_HANDLE_VALUE))) {
  1955. Err = ERROR_INVALID_PARAMETER;
  1956. leave;
  1957. }
  1958. if(hwndParent && !IsWindow(hwndParent)) {
  1959. hwndParent = NULL;
  1960. }
  1961. if(InfFileName) {
  1962. //
  1963. // Open the INF, and ensure that the same logging context is used
  1964. // for all operations.
  1965. //
  1966. Err = GLE_FN_CALL(INVALID_HANDLE_VALUE,
  1967. hInf = SetupOpenInfFile(InfFileName,
  1968. NULL,
  1969. INF_STYLE_WIN4,
  1970. NULL)
  1971. );
  1972. if(Err != NO_ERROR) {
  1973. leave;
  1974. }
  1975. Err = InheritLogContext(((PLOADED_INF)hInf)->LogContext,
  1976. &LogContext
  1977. );
  1978. if(Err != NO_ERROR) {
  1979. //
  1980. // Since we're using log context inheritance to create a log
  1981. // context, this failure must be considered critical.
  1982. //
  1983. leave;
  1984. }
  1985. } else {
  1986. //
  1987. // No INF to worry about--just need a log context for the stuff
  1988. // we're doing directly.
  1989. //
  1990. Err = CreateLogContext(NULL, TRUE, &LogContext);
  1991. if(Err != NO_ERROR) {
  1992. leave;
  1993. }
  1994. }
  1995. if(InterfaceClassGuid) {
  1996. //
  1997. // Copy this GUID into our ClassGuid variable, which is used for
  1998. // both installer and device interface classes.
  1999. //
  2000. CopyMemory(&ClassGuid, InterfaceClassGuid, sizeof(ClassGuid));
  2001. ClassGuidIsValid = TRUE;
  2002. //
  2003. // Legacy (compatibility) class name is not needed for device
  2004. // interface classes.
  2005. //
  2006. ClassName = NULL;
  2007. pSetupStringFromGuid(&ClassGuid,
  2008. ClassGuidStringBuffer,
  2009. SIZECHARS(ClassGuidStringBuffer)
  2010. );
  2011. WriteLogEntry(LogContext,
  2012. DRIVER_LOG_INFO,
  2013. MSG_LOG_DO_INTERFACE_CLASS_INSTALL,
  2014. NULL, // text message
  2015. ClassGuidStringBuffer
  2016. );
  2017. } else {
  2018. PCTSTR pInfGuidString;
  2019. //
  2020. // Retrieve the class GUID from the INF. If it has no class GUID,
  2021. // then we can't install from it (even if it specifies the class
  2022. // name).
  2023. //
  2024. if(!(pInfGuidString = pSetupGetVersionDatum(
  2025. &((PLOADED_INF)hInf)->VersionBlock,
  2026. pszClassGuid))
  2027. || (pSetupGuidFromString(pInfGuidString, &ClassGuid) != NO_ERROR)) {
  2028. Err = ERROR_INVALID_CLASS;
  2029. leave;
  2030. }
  2031. ClassGuidIsValid = TRUE;
  2032. if(!MYVERIFY(SUCCEEDED(StringCchCopy(ClassGuidStringBuffer,
  2033. SIZECHARS(ClassGuidStringBuffer),
  2034. pInfGuidString
  2035. )))) {
  2036. //
  2037. // "will never fail"
  2038. // but if it does, fail securely
  2039. //
  2040. Err = ERROR_INVALID_CLASS;
  2041. leave;
  2042. }
  2043. //
  2044. // We'll need to get the class name out of the INF as well.
  2045. //
  2046. if(!(ClassName = pSetupGetVersionDatum(&((PLOADED_INF)hInf)->VersionBlock,
  2047. pszClass))) {
  2048. Err = ERROR_INVALID_CLASS;
  2049. leave;
  2050. }
  2051. WriteLogEntry(LogContext,
  2052. DRIVER_LOG_INFO,
  2053. MSG_LOG_DO_CLASS_INSTALL,
  2054. NULL, // text message
  2055. ClassGuidStringBuffer,
  2056. ClassName
  2057. );
  2058. }
  2059. //
  2060. // First, attempt to open the key (i.e., not create it). If that
  2061. // fails, then we'll try to create it. That way, we can keep track of
  2062. // whether clean-up is required if an error occurs.
  2063. //
  2064. if(CR_SUCCESS != CM_Open_Class_Key_Ex(&ClassGuid,
  2065. ClassName,
  2066. KEY_READ | KEY_WRITE,
  2067. RegDisposition_OpenExisting,
  2068. &hKey,
  2069. InterfaceClassGuid ? CM_OPEN_CLASS_KEY_INTERFACE
  2070. : CM_OPEN_CLASS_KEY_INSTALLER,
  2071. NULL))
  2072. {
  2073. CONFIGRET cr;
  2074. //
  2075. // The key doesn't already exist--we've got to create it.
  2076. //
  2077. cr = CM_Open_Class_Key_Ex(&ClassGuid,
  2078. ClassName,
  2079. KEY_READ | KEY_WRITE,
  2080. RegDisposition_OpenAlways,
  2081. &hKey,
  2082. (InterfaceClassGuid ? CM_OPEN_CLASS_KEY_INTERFACE
  2083. : CM_OPEN_CLASS_KEY_INSTALLER),
  2084. NULL
  2085. );
  2086. if(cr != CR_SUCCESS) {
  2087. hKey = INVALID_HANDLE_VALUE; // ensure key handle still invalid
  2088. Err = CR_TO_SP(cr, ERROR_INVALID_DATA);
  2089. leave;
  2090. }
  2091. KeyNewlyCreated = TRUE;
  2092. }
  2093. if(hInf == INVALID_HANDLE_VALUE) {
  2094. //
  2095. // We've done all we need to do to install this device interface.
  2096. //
  2097. leave;
  2098. } else {
  2099. //
  2100. // Append the layout INF, if necessary.
  2101. //
  2102. SetupOpenAppendInfFile(NULL, hInf, NULL);
  2103. }
  2104. if(InterfaceClassGuid) {
  2105. //
  2106. // Look for an entry for this interface class in the
  2107. // [InterfaceInstall32] section of the INF.
  2108. //
  2109. if(!SetupFindFirstLine(hInf,
  2110. pszInterfaceInstall32,
  2111. ClassGuidStringBuffer,
  2112. &InterfaceClassInstallLine)) {
  2113. //
  2114. // No install entry in this INF--we're done.
  2115. //
  2116. leave;
  2117. }
  2118. //
  2119. // Make sure the Flags field is zero.
  2120. //
  2121. if(SetupGetIntField(&InterfaceClassInstallLine, 2, (PINT)&InstallFlags) && InstallFlags) {
  2122. Err = ERROR_BAD_INTERFACE_INSTALLSECT;
  2123. leave;
  2124. }
  2125. if((!(UndecoratedInstallSection = pSetupGetField(&InterfaceClassInstallLine, 1)))
  2126. || !(*UndecoratedInstallSection))
  2127. {
  2128. //
  2129. // No install section was given--we're done.
  2130. //
  2131. leave;
  2132. }
  2133. } else {
  2134. UndecoratedInstallSection = pszClassInstall32;
  2135. ZeroMemory(&RegContext, sizeof(RegContext));
  2136. RegContext.Flags |= INF_PFLAG_CLASSPROP;
  2137. RegContext.ClassGuid = &ClassGuid;
  2138. //
  2139. // Leave RegContext.hMachine as NULL, since we don't support
  2140. // remote installation of either device setup or device interface
  2141. // classes.
  2142. //
  2143. }
  2144. //
  2145. // Get the 'real' (potentially OS/architecture-specific) class install
  2146. // section name.
  2147. //
  2148. Err = GLE_FN_CALL(FALSE,
  2149. SetupDiGetActualSectionToInstall(
  2150. hInf,
  2151. UndecoratedInstallSection,
  2152. ClassInstallSectionName,
  2153. SIZECHARS(ClassInstallSectionName),
  2154. &ClassInstallSectionNameLen,
  2155. &SectionExtension)
  2156. );
  2157. if(Err == NO_ERROR) {
  2158. MYASSERT(ClassInstallSectionNameLen > 1);
  2159. ClassInstallSectionNameLen--; // don't want this to include null
  2160. } else {
  2161. leave;
  2162. }
  2163. //
  2164. // Also say what section is about to be installed.
  2165. //
  2166. WriteLogEntry(LogContext,
  2167. DRIVER_LOG_VERBOSE,
  2168. MSG_LOG_CLASS_SECTION,
  2169. NULL,
  2170. ClassInstallSectionName
  2171. );
  2172. //
  2173. // If this is the undecorated name, then make sure that the section
  2174. // actually exists.
  2175. //
  2176. if(!SectionExtension && (SetupGetLineCount(hInf, ClassInstallSectionName) == -1)) {
  2177. Err = ERROR_SECTION_NOT_FOUND;
  2178. WriteLogEntry(LogContext,
  2179. DRIVER_LOG_ERROR,
  2180. MSG_LOG_NOSECTION,
  2181. NULL,
  2182. ClassInstallSectionName
  2183. );
  2184. leave;
  2185. }
  2186. if(!(Flags & DI_NOVCP)) {
  2187. //
  2188. // Since we may need to check the queued files to determine whether
  2189. // file copy is necessary, we have to open our own queue, and
  2190. // commit it ourselves.
  2191. //
  2192. Err = GLE_FN_CALL(INVALID_HANDLE_VALUE,
  2193. FileQueue = SetupOpenFileQueue()
  2194. );
  2195. if(Err == NO_ERROR) {
  2196. CloseFileQueue = TRUE;
  2197. } else {
  2198. leave;
  2199. }
  2200. NoProgressUI = (GuiSetupInProgress ||
  2201. (GlobalSetupFlags & PSPGF_NONINTERACTIVE) ||
  2202. (Flags & DI_QUIETINSTALL));
  2203. if(!(MsgHandlerContext = SetupInitDefaultQueueCallbackEx(
  2204. hwndParent,
  2205. (NoProgressUI ? INVALID_HANDLE_VALUE : NULL),
  2206. 0,
  2207. 0,
  2208. NULL))) {
  2209. //
  2210. // This routine doesn't set last error, but the only reason it
  2211. // can fail is due to insufficient memory...
  2212. //
  2213. Err = ERROR_NOT_ENOUGH_MEMORY;
  2214. leave;
  2215. }
  2216. MsgHandler = SetupDefaultQueueCallback;
  2217. }
  2218. //
  2219. // Replace the file queue's log context with current, if it's never
  2220. // been used. Failure to inherit is OK, because we know the file queue
  2221. // has its own log context. Thus, the worst that can happen is the log
  2222. // entries go to two different sections.
  2223. //
  2224. InheritLogContext(LogContext, &((PSP_FILE_QUEUE)FileQueue)->LogContext);
  2225. Err = pSetupInstallFiles(hInf,
  2226. NULL,
  2227. ClassInstallSectionName,
  2228. NULL,
  2229. NULL,
  2230. NULL,
  2231. SP_COPY_NEWER_OR_SAME | SP_COPY_LANGUAGEAWARE |
  2232. ((Flags & DI_NOBROWSE) ? SP_COPY_NOBROWSE : 0),
  2233. NULL,
  2234. FileQueue,
  2235. //
  2236. // This flag is ignored by pSetupInstallFiles
  2237. // because we don't pass a callback here and we
  2238. // pass a user-defined file queue. (In other words
  2239. // we're not committing the queue so there's no
  2240. // callback function to deal with, and the callback
  2241. // would be the guy who would care about ansi vs unicode.)
  2242. //
  2243. TRUE
  2244. );
  2245. if(CloseFileQueue && (Err == NO_ERROR)) {
  2246. //
  2247. // Call _SetupVerifyQueuedCatalogs separately (i.e., don't let it
  2248. // happen automatically as a result of scanning/committing the
  2249. // queue that happens below). We do this beforehand so that we
  2250. // know what unique name was generated when an OEM INF was
  2251. // installed into %windir%\Inf (in case we need to delete the
  2252. // INF/PNF/CAT files later if we encounter an error).
  2253. //
  2254. WriteLogEntry(LogContext,
  2255. DRIVER_LOG_TIME,
  2256. MSG_LOG_BEGIN_INSTCLASS_VERIFY_CAT_TIME,
  2257. NULL // text message
  2258. );
  2259. //
  2260. // (NOTE: We don't have the context in this routine to determine
  2261. // whether or not the INF is from the internet. For now, just
  2262. // assume it isn't.)
  2263. //
  2264. Err = _SetupVerifyQueuedCatalogs(
  2265. hwndParent,
  2266. FileQueue,
  2267. VERCAT_INSTALL_INF_AND_CAT,
  2268. szNewName,
  2269. &OemInfFileToCopy
  2270. );
  2271. WriteLogEntry(LogContext,
  2272. DRIVER_LOG_TIME,
  2273. MSG_LOG_END_INSTCLASS_VERIFY_CAT_TIME,
  2274. NULL // text message
  2275. );
  2276. if(Err == NO_ERROR) {
  2277. //
  2278. // We successfully queued up the file operations--now we need
  2279. // to commit the queue. First off, though, we should check to
  2280. // see if the files are already there. (If the 'force copy'
  2281. // flag is set, then we don't care if the files are already
  2282. // there--we always need to copy them in that case.)
  2283. //
  2284. if(Flags & DI_FORCECOPY) {
  2285. //
  2286. // always copy the files.
  2287. //
  2288. ScanQueueResult = 0;
  2289. } else {
  2290. //
  2291. // Determine whether the queue actually needs to be
  2292. // committed.
  2293. //
  2294. // ScanQueueResult can have 1 of 3 values:
  2295. //
  2296. // 0: Some files were missing or invalid (i.e., digital
  2297. // signatures weren't verified;
  2298. // Must commit queue.
  2299. //
  2300. // 1: All files to be copied are already present/valid, and
  2301. // the queue is empty;
  2302. // Can skip committing queue.
  2303. //
  2304. // 2: All files to be copied are already present/valid, but
  2305. // del/ren queues not empty. Must commit queue. The
  2306. // copy queue will have been emptied, so only del/ren
  2307. // functions will be performed.
  2308. //
  2309. if(!SetupScanFileQueue(FileQueue,
  2310. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  2311. hwndParent,
  2312. NULL,
  2313. NULL,
  2314. &ScanQueueResult)) {
  2315. //
  2316. // SetupScanFileQueue should really never
  2317. // fail when you don't ask it to call a
  2318. // callback routine, but if it does, just
  2319. // go ahead and commit the queue.
  2320. //
  2321. ScanQueueResult = 0;
  2322. }
  2323. }
  2324. if(ScanQueueResult != 1) {
  2325. //
  2326. // Copy enqueued files. In this case the callback is
  2327. // SetupDefaultQueueCallback, so we know it's native char
  2328. // width.
  2329. //
  2330. Err = GLE_FN_CALL(FALSE,
  2331. _SetupCommitFileQueue(hwndParent,
  2332. FileQueue,
  2333. MsgHandler,
  2334. MsgHandlerContext,
  2335. TRUE)
  2336. );
  2337. }
  2338. }
  2339. }
  2340. if(Err != NO_ERROR) {
  2341. leave;
  2342. }
  2343. //
  2344. // If we get to here, then the file copying was successful--now we can
  2345. // perform the rest of the installation. We don't pass a callback so we
  2346. // don't worry about ansi vs unicode issues here.
  2347. //
  2348. Err = GLE_FN_CALL(FALSE,
  2349. _SetupInstallFromInfSection(
  2350. NULL,
  2351. hInf,
  2352. ClassInstallSectionName,
  2353. SPINST_INIFILES
  2354. | SPINST_REGISTRY
  2355. | SPINST_INI2REG
  2356. | SPINST_BITREG
  2357. | SPINST_REGSVR
  2358. | SPINST_UNREGSVR
  2359. | SPINST_PROFILEITEMS,
  2360. hKey,
  2361. NULL,
  2362. 0,
  2363. NULL,
  2364. NULL,
  2365. INVALID_HANDLE_VALUE,
  2366. NULL,
  2367. TRUE,
  2368. (InterfaceClassGuid ? NULL : &RegContext))
  2369. );
  2370. if(Err != NO_ERROR) {
  2371. leave;
  2372. }
  2373. //
  2374. // The class installer might want to install a Services section. This
  2375. // allows device setup class registration to include installation of a
  2376. // class-wide driver.
  2377. //
  2378. WriteLogEntry(LogContext,
  2379. DRIVER_LOG_TIME,
  2380. MSG_LOG_BEGIN_SERVICE_TIME,
  2381. NULL // text message
  2382. );
  2383. //
  2384. // The install section name is of the form:
  2385. //
  2386. // ClassInstall32[.<ext>].Services
  2387. //
  2388. hr = StringCchCopy(
  2389. &(ClassInstallSectionName[ClassInstallSectionNameLen]),
  2390. SIZECHARS(ClassInstallSectionName) - ClassInstallSectionNameLen,
  2391. pszServicesSectionSuffix
  2392. );
  2393. if(FAILED(hr)) {
  2394. Err = HRESULT_CODE(hr);
  2395. leave;
  2396. }
  2397. Err = InstallNtService(NULL,
  2398. hInf,
  2399. InfFileName,
  2400. ClassInstallSectionName,
  2401. NULL,
  2402. SPSVCINST_NO_DEVINST_CHECK,
  2403. &NullDriverInstall
  2404. );
  2405. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2406. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  2407. }
  2408. if(hKey != INVALID_HANDLE_VALUE) {
  2409. RegCloseKey(hKey);
  2410. //
  2411. // NTRAID#NTBUG9-660148-2002/07/05-lonnym - need to clean up interface keys too!
  2412. //
  2413. if((Err != NO_ERROR) && KeyNewlyCreated && !InterfaceClassGuid) {
  2414. //
  2415. // We hit an error, and the class installer key didn't previously
  2416. // exist, so we want to remove it.
  2417. //
  2418. CM_Delete_Class_Key_Ex(&ClassGuid,
  2419. CM_DELETE_CLASS_SUBKEYS,
  2420. NULL
  2421. );
  2422. }
  2423. }
  2424. if(CloseFileQueue) {
  2425. SetupCloseFileQueue(FileQueue);
  2426. }
  2427. if(MsgHandlerContext) {
  2428. SetupTermDefaultQueueCallback(MsgHandlerContext);
  2429. }
  2430. if(hInf != INVALID_HANDLE_VALUE) {
  2431. SetupCloseInfFile(hInf);
  2432. }
  2433. if(Err == NO_ERROR) {
  2434. //
  2435. // If we're >= DRIVER_LOG_INFO, give a +ve affirmation of install.
  2436. //
  2437. WriteLogEntry(LogContext,
  2438. DRIVER_LOG_INFO,
  2439. MSG_LOG_CLASS_INSTALLED,
  2440. NULL,
  2441. NULL
  2442. );
  2443. } else {
  2444. //
  2445. // Log an error about the failure encountered.
  2446. //
  2447. WriteLogEntry(LogContext,
  2448. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  2449. MSG_LOG_CLASS_ERROR_ENCOUNTERED,
  2450. NULL,
  2451. (ClassGuidIsValid ? ClassGuidStringBuffer : TEXT("*"))
  2452. );
  2453. WriteLogError(LogContext, DRIVER_LOG_ERROR, Err);
  2454. //
  2455. // If we copied the OEM INF into the INF directory under a
  2456. // newly-generated name, delete it now.
  2457. //
  2458. if(OemInfFileToCopy) {
  2459. pSetupUninstallOEMInf(szNewName,
  2460. LogContext,
  2461. SUOI_FORCEDELETE,
  2462. NULL
  2463. );
  2464. }
  2465. }
  2466. if(LogContext) {
  2467. DeleteLogContext(LogContext);
  2468. }
  2469. SetLastError(Err);
  2470. return (Err == NO_ERROR);
  2471. }
  2472. //
  2473. // ANSI version
  2474. //
  2475. BOOL
  2476. WINAPI
  2477. SetupDiInstallClassA(
  2478. IN HWND hwndParent, OPTIONAL
  2479. IN PCSTR InfFileName,
  2480. IN DWORD Flags,
  2481. IN HSPFILEQ FileQueue OPTIONAL
  2482. )
  2483. {
  2484. PCWSTR UnicodeInfFileName = NULL;
  2485. DWORD rc;
  2486. try {
  2487. rc = pSetupCaptureAndConvertAnsiArg(InfFileName, &UnicodeInfFileName);
  2488. if(rc != NO_ERROR) {
  2489. leave;
  2490. }
  2491. rc = GLE_FN_CALL(FALSE,
  2492. SetupDiInstallClassExW(hwndParent,
  2493. UnicodeInfFileName,
  2494. Flags,
  2495. FileQueue,
  2496. NULL,
  2497. NULL,
  2498. NULL)
  2499. );
  2500. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2501. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  2502. }
  2503. if(UnicodeInfFileName) {
  2504. MyFree(UnicodeInfFileName);
  2505. }
  2506. SetLastError(rc);
  2507. return (rc == NO_ERROR);
  2508. }
  2509. BOOL
  2510. WINAPI
  2511. SetupDiInstallClass(
  2512. IN HWND hwndParent, OPTIONAL
  2513. IN PCTSTR InfFileName,
  2514. IN DWORD Flags,
  2515. IN HSPFILEQ FileQueue OPTIONAL
  2516. )
  2517. /*++
  2518. Routine Description:
  2519. This routine installs the [ClassInstall32] section of the specified INF.
  2520. Arguments:
  2521. hwndParent - Optionally, supplies the handle of the parent window for any
  2522. UI brought up as a result of installing this class.
  2523. InfFileName - Supplies the name of the INF file containing a
  2524. [ClassInstall32] section.
  2525. Flags - Flags that control the installation. May be a combination of the
  2526. following:
  2527. DI_NOVCP - This flag should be specified if HSPFILEQ is supplied. This
  2528. instructs SetupInstallFromInfSection to not create a queue of its
  2529. own, and instead to use the caller-supplied one. If this flag is
  2530. specified, then no file copying will be done.
  2531. DI_NOBROWSE - This flag should be specified if no file browsing should
  2532. be allowed in the event a copy operation cannot find a specified
  2533. file. If the user supplies their own file queue, then this flag is
  2534. ignored.
  2535. DI_FORCECOPY - This flag should be specified if the files should always
  2536. be copied, even if they're already present on the user's machine
  2537. (i.e., don't ask the user if they want to keep their existing
  2538. files). If the user supplies their own file queue, then this flag
  2539. is ignored.
  2540. DI_QUIETINSTALL - This flag should be specified if UI should be
  2541. suppressed unless absolutely necessary (i.e., no progress dialog).
  2542. If the user supplies their own queue, then this flag is ignored.
  2543. (NOTE: During GUI-mode setup on Windows NT, quiet-install behavior
  2544. is always employed in the absence of a user-supplied file queue.)
  2545. FileQueue - If the DI_NOVCP flag is specified, then this parameter supplies
  2546. a handle to a file queue where file operations are to be queued (but
  2547. not committed).
  2548. Return Value:
  2549. If the function succeeds, the return value is TRUE.
  2550. If the function fails, the return value is FALSE. To get extended error
  2551. information, call GetLastError.
  2552. Remarks:
  2553. This API is generally called by the "New Hardware Found" process when it
  2554. installs a device of a new device setup class.
  2555. --*/
  2556. {
  2557. DWORD Err;
  2558. try {
  2559. Err = GLE_FN_CALL(FALSE,
  2560. SetupDiInstallClassEx(hwndParent,
  2561. InfFileName,
  2562. Flags,
  2563. FileQueue,
  2564. NULL,
  2565. NULL,
  2566. NULL)
  2567. );
  2568. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2569. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  2570. }
  2571. SetLastError(Err);
  2572. return (Err == NO_ERROR);
  2573. }
  2574. //
  2575. // ANSI version
  2576. //
  2577. BOOL
  2578. WINAPI
  2579. SetupDiGetHwProfileFriendlyNameA(
  2580. IN DWORD HwProfile,
  2581. OUT PSTR FriendlyName,
  2582. IN DWORD FriendlyNameSize,
  2583. OUT PDWORD RequiredSize OPTIONAL
  2584. )
  2585. {
  2586. DWORD Err;
  2587. try {
  2588. Err = GLE_FN_CALL(FALSE,
  2589. SetupDiGetHwProfileFriendlyNameExA(
  2590. HwProfile,
  2591. FriendlyName,
  2592. FriendlyNameSize,
  2593. RequiredSize,
  2594. NULL,
  2595. NULL)
  2596. );
  2597. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2598. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  2599. }
  2600. SetLastError(Err);
  2601. return (Err == NO_ERROR);
  2602. }
  2603. BOOL
  2604. WINAPI
  2605. SetupDiGetHwProfileFriendlyName(
  2606. IN DWORD HwProfile,
  2607. OUT PTSTR FriendlyName,
  2608. IN DWORD FriendlyNameSize,
  2609. OUT PDWORD RequiredSize OPTIONAL
  2610. )
  2611. /*++
  2612. Routine Description:
  2613. See SetupDiGetHwProfileFriendlyNameEx for details.
  2614. --*/
  2615. {
  2616. DWORD Err;
  2617. try {
  2618. Err = GLE_FN_CALL(FALSE,
  2619. SetupDiGetHwProfileFriendlyNameEx(
  2620. HwProfile,
  2621. FriendlyName,
  2622. FriendlyNameSize,
  2623. RequiredSize,
  2624. NULL,
  2625. NULL)
  2626. );
  2627. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2628. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  2629. }
  2630. SetLastError(Err);
  2631. return (Err == NO_ERROR);
  2632. }
  2633. //
  2634. // ANSI version
  2635. //
  2636. BOOL
  2637. WINAPI
  2638. SetupDiGetHwProfileFriendlyNameExA(
  2639. IN DWORD HwProfile,
  2640. OUT PSTR FriendlyName,
  2641. IN DWORD FriendlyNameSize,
  2642. OUT PDWORD RequiredSize, OPTIONAL
  2643. IN PCSTR MachineName, OPTIONAL
  2644. IN PVOID Reserved
  2645. )
  2646. {
  2647. WCHAR UnicodeName[MAX_PROFILE_LEN];
  2648. PSTR AnsiName = NULL;
  2649. DWORD rc;
  2650. DWORD LocalRequiredSize;
  2651. PCWSTR UnicodeMachineName = NULL;
  2652. HRESULT hr;
  2653. try {
  2654. //
  2655. // If you pass a NULL buffer pointer, the size had better be zero!
  2656. //
  2657. if(!FriendlyName && FriendlyNameSize) {
  2658. rc = ERROR_INVALID_PARAMETER;
  2659. leave;
  2660. }
  2661. if(MachineName) {
  2662. rc = pSetupCaptureAndConvertAnsiArg(MachineName, &UnicodeMachineName);
  2663. if(rc != NO_ERROR) {
  2664. leave;
  2665. }
  2666. }
  2667. rc = GLE_FN_CALL(FALSE,
  2668. SetupDiGetHwProfileFriendlyNameExW(
  2669. HwProfile,
  2670. UnicodeName,
  2671. SIZECHARS(UnicodeName),
  2672. &LocalRequiredSize,
  2673. UnicodeMachineName,
  2674. Reserved)
  2675. );
  2676. if(rc != NO_ERROR) {
  2677. leave;
  2678. }
  2679. AnsiName = pSetupUnicodeToAnsi(UnicodeName);
  2680. if(!AnsiName) {
  2681. rc = ERROR_NOT_ENOUGH_MEMORY;
  2682. leave;
  2683. }
  2684. LocalRequiredSize = lstrlenA(AnsiName) + 1;
  2685. if(RequiredSize) {
  2686. *RequiredSize = LocalRequiredSize;
  2687. }
  2688. if(!FriendlyName) {
  2689. rc = ERROR_INSUFFICIENT_BUFFER;
  2690. leave;
  2691. }
  2692. hr = StringCchCopyA(FriendlyName,
  2693. (size_t)FriendlyNameSize,
  2694. AnsiName
  2695. );
  2696. if(FAILED(hr)) {
  2697. rc = HRESULT_CODE(hr);
  2698. }
  2699. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2700. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  2701. }
  2702. if(AnsiName) {
  2703. MyFree(AnsiName);
  2704. }
  2705. if(UnicodeMachineName) {
  2706. MyFree(UnicodeMachineName);
  2707. }
  2708. SetLastError(rc);
  2709. return (rc == NO_ERROR);
  2710. }
  2711. BOOL
  2712. WINAPI
  2713. SetupDiGetHwProfileFriendlyNameEx(
  2714. IN DWORD HwProfile,
  2715. OUT PTSTR FriendlyName,
  2716. IN DWORD FriendlyNameSize,
  2717. OUT PDWORD RequiredSize, OPTIONAL
  2718. IN PCTSTR MachineName, OPTIONAL
  2719. IN PVOID Reserved
  2720. )
  2721. /*++
  2722. Routine Description:
  2723. This routine retrieves the friendly name associated with a hardware profile
  2724. ID.
  2725. Arguments:
  2726. HwProfile - Supplies the hardware profile ID whose friendly name is to be
  2727. retrieved. If this parameter is 0, then the friendly name for the
  2728. current hardware profile is retrieved.
  2729. FriendlyName - Supplies the address of a character buffer that receives the
  2730. friendly name of the hardware profile.
  2731. FriendlyNameSize - Supplies the size, in characters, of the FriendlyName
  2732. buffer.
  2733. RequiredSize - Optionally, supplies the address of a variable that receives
  2734. the number of characters required to store the friendly name (including
  2735. terminating NULL).
  2736. MachineName - Optionally, supplies the name of the remote machine
  2737. containing the hardware profile whose friendly name is to be retrieved.
  2738. If this parameter is not specified, the local machine is used.
  2739. Reserved - Reserved for future use--must be NULL.
  2740. Return Value:
  2741. If the function succeeds, the return value is TRUE.
  2742. If the function fails, the return value is FALSE. To get extended error
  2743. information, call GetLastError.
  2744. --*/
  2745. {
  2746. DWORD Err = ERROR_INVALID_HWPROFILE;
  2747. HWPROFILEINFO HwProfInfo;
  2748. ULONG i;
  2749. CONFIGRET cr;
  2750. size_t NameLen;
  2751. HMACHINE hMachine = NULL;
  2752. HRESULT hr;
  2753. try {
  2754. //
  2755. // If you pass a NULL buffer pointer, the size had better be zero!
  2756. //
  2757. if(!FriendlyName && FriendlyNameSize) {
  2758. Err = ERROR_INVALID_PARAMETER;
  2759. leave;
  2760. }
  2761. //
  2762. // Make sure the caller didn't pass us anything in the Reserved
  2763. // parameter.
  2764. //
  2765. if(Reserved) {
  2766. Err = ERROR_INVALID_PARAMETER;
  2767. leave;
  2768. }
  2769. //
  2770. // If the caller specified a remote machine name, connect to that
  2771. // machine.
  2772. //
  2773. if(MachineName) {
  2774. cr = CM_Connect_Machine(MachineName, &hMachine);
  2775. if(cr != CR_SUCCESS) {
  2776. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2777. leave;
  2778. }
  2779. }
  2780. //
  2781. // If a hardware profile ID of 0 is specified, then retrieve
  2782. // information about the current hardware profile, otherwise, enumerate
  2783. // the hardware profiles, looking for the one specified.
  2784. //
  2785. if(HwProfile) {
  2786. i = 0;
  2787. } else {
  2788. i = 0xFFFFFFFF;
  2789. }
  2790. do {
  2791. if((cr = CM_Get_Hardware_Profile_Info_Ex(i, &HwProfInfo, 0, hMachine)) == CR_SUCCESS) {
  2792. //
  2793. // Hardware profile info retrieved--see if it's what we're
  2794. // looking for.
  2795. //
  2796. if(!HwProfile || (HwProfInfo.HWPI_ulHWProfile == HwProfile)) {
  2797. hr = StringCchLength(HwProfInfo.HWPI_szFriendlyName,
  2798. SIZECHARS(HwProfInfo.HWPI_szFriendlyName),
  2799. &NameLen
  2800. );
  2801. if(FAILED(hr)) {
  2802. //
  2803. // CM API gave us garbage!!!
  2804. //
  2805. MYASSERT(FALSE);
  2806. Err = ERROR_INVALID_DATA;
  2807. leave;
  2808. }
  2809. NameLen++; // include terminating null char
  2810. if(RequiredSize) {
  2811. *RequiredSize = (DWORD)NameLen;
  2812. }
  2813. if((DWORD)NameLen > FriendlyNameSize) {
  2814. Err = ERROR_INSUFFICIENT_BUFFER;
  2815. } else {
  2816. Err = NO_ERROR;
  2817. CopyMemory(FriendlyName,
  2818. HwProfInfo.HWPI_szFriendlyName,
  2819. NameLen * sizeof(TCHAR)
  2820. );
  2821. }
  2822. break;
  2823. }
  2824. //
  2825. // This wasn't the profile we wanted--go on to the next one.
  2826. //
  2827. i++;
  2828. } else if(!HwProfile || (cr != CR_NO_SUCH_VALUE)) {
  2829. //
  2830. // We should abort on any error other than CR_NO_SUCH_VALUE,
  2831. // otherwise we might loop forever!
  2832. //
  2833. Err = ERROR_INVALID_DATA;
  2834. break;
  2835. }
  2836. } while(cr != CR_NO_SUCH_VALUE);
  2837. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2838. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  2839. }
  2840. if(hMachine) {
  2841. CM_Disconnect_Machine(hMachine);
  2842. }
  2843. SetLastError(Err);
  2844. return (Err == NO_ERROR);
  2845. }
  2846. BOOL
  2847. WINAPI
  2848. SetupDiGetHwProfileList(
  2849. OUT PDWORD HwProfileList,
  2850. IN DWORD HwProfileListSize,
  2851. OUT PDWORD RequiredSize,
  2852. OUT PDWORD CurrentlyActiveIndex OPTIONAL
  2853. )
  2854. /*++
  2855. Routine Description:
  2856. This routine retrieves a list of all currently-defined hardware profile
  2857. IDs.
  2858. Arguments:
  2859. HwProfileList - Supplies the address of an array of DWORDs that will
  2860. receive the list of currently defined hardware profile IDs.
  2861. HwProfileListSize - Supplies the number of DWORDs in the HwProfileList
  2862. array.
  2863. RequiredSize - Supplies the address of a variable that receives the number
  2864. of hardware profiles currently defined. If this number is larger than
  2865. HwProfileListSize, then the list will be truncated to fit the array
  2866. size, and this value will indicate the array size that would be
  2867. required to store the entire list (the function will fail, with
  2868. GetLastError returning ERROR_INSUFFICIENT_BUFFER in that case).
  2869. CurrentlyActiveIndex - Optionally, supplies the address of a variable that
  2870. receives the index within the HwProfileList array of the currently
  2871. active hardware profile.
  2872. Return Value:
  2873. If the function succeeds, the return value is TRUE.
  2874. If the function fails, the return value is FALSE. To get extended error
  2875. information, call GetLastError.
  2876. --*/
  2877. {
  2878. DWORD Err;
  2879. try {
  2880. Err = GLE_FN_CALL(FALSE,
  2881. SetupDiGetHwProfileListEx(HwProfileList,
  2882. HwProfileListSize,
  2883. RequiredSize,
  2884. CurrentlyActiveIndex,
  2885. NULL,
  2886. NULL)
  2887. );
  2888. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2889. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  2890. }
  2891. SetLastError(Err);
  2892. return (Err == NO_ERROR);
  2893. }
  2894. //
  2895. // ANSI version
  2896. //
  2897. BOOL
  2898. WINAPI
  2899. SetupDiGetHwProfileListExA(
  2900. OUT PDWORD HwProfileList,
  2901. IN DWORD HwProfileListSize,
  2902. OUT PDWORD RequiredSize,
  2903. OUT PDWORD CurrentlyActiveIndex, OPTIONAL
  2904. IN PCSTR MachineName, OPTIONAL
  2905. IN PVOID Reserved
  2906. )
  2907. {
  2908. PCWSTR UnicodeMachineName = NULL;
  2909. DWORD rc;
  2910. try {
  2911. if(MachineName) {
  2912. rc = pSetupCaptureAndConvertAnsiArg(MachineName, &UnicodeMachineName);
  2913. if(rc != NO_ERROR) {
  2914. leave;
  2915. }
  2916. }
  2917. rc = GLE_FN_CALL(FALSE,
  2918. SetupDiGetHwProfileListExW(HwProfileList,
  2919. HwProfileListSize,
  2920. RequiredSize,
  2921. CurrentlyActiveIndex,
  2922. UnicodeMachineName,
  2923. Reserved)
  2924. );
  2925. } except(pSetupExceptionFilter(GetExceptionCode())) {
  2926. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  2927. }
  2928. if(UnicodeMachineName) {
  2929. MyFree(UnicodeMachineName);
  2930. }
  2931. SetLastError(rc);
  2932. return (rc == NO_ERROR);
  2933. }
  2934. BOOL
  2935. WINAPI
  2936. SetupDiGetHwProfileListEx(
  2937. OUT PDWORD HwProfileList,
  2938. IN DWORD HwProfileListSize,
  2939. OUT PDWORD RequiredSize,
  2940. OUT PDWORD CurrentlyActiveIndex, OPTIONAL
  2941. IN PCTSTR MachineName, OPTIONAL
  2942. IN PVOID Reserved
  2943. )
  2944. /*++
  2945. Routine Description:
  2946. This routine retrieves a list of all currently-defined hardware profile
  2947. IDs.
  2948. Arguments:
  2949. HwProfileList - Supplies the address of an array of DWORDs that will
  2950. receive the list of currently defined hardware profile IDs.
  2951. HwProfileListSize - Supplies the number of DWORDs in the HwProfileList
  2952. array.
  2953. RequiredSize - Supplies the address of a variable that receives the number
  2954. of hardware profiles currently defined. If this number is larger than
  2955. HwProfileListSize, then the list will be truncated to fit the array
  2956. size, and this value will indicate the array size that would be
  2957. required to store the entire list (the function will fail, with
  2958. GetLastError returning ERROR_INSUFFICIENT_BUFFER in that case).
  2959. CurrentlyActiveIndex - Optionally, supplies the address of a variable that
  2960. receives the index within the HwProfileList array of the currently
  2961. active hardware profile.
  2962. MachineName - Optionally, specifies the name of the remote machine to
  2963. retrieve a list of hardware profiles for.
  2964. Reserved - Reserved for future use--must be NULL.
  2965. Return Value:
  2966. If the function succeeds, the return value is TRUE.
  2967. If the function fails, the return value is FALSE. To get extended error
  2968. information, call GetLastError.
  2969. --*/
  2970. {
  2971. DWORD Err = NO_ERROR;
  2972. DWORD CurHwProfile;
  2973. HWPROFILEINFO HwProfInfo;
  2974. ULONG i;
  2975. CONFIGRET cr = CR_SUCCESS;
  2976. HMACHINE hMachine = NULL;
  2977. try {
  2978. //
  2979. // Make sure the caller didn't pass us anything in the Reserved
  2980. // parameter.
  2981. //
  2982. if(Reserved) {
  2983. Err = ERROR_INVALID_PARAMETER;
  2984. leave;
  2985. }
  2986. //
  2987. // If the caller specified a null buffer pointer, its size had better
  2988. // be zero.
  2989. //
  2990. if(!HwProfileList && HwProfileListSize) {
  2991. Err = ERROR_INVALID_PARAMETER;
  2992. leave;
  2993. }
  2994. //
  2995. // If the caller specified a remote machine name, connect to that
  2996. // machine now.
  2997. //
  2998. if(MachineName) {
  2999. cr = CM_Connect_Machine(MachineName, &hMachine);
  3000. if(cr != CR_SUCCESS) {
  3001. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  3002. leave;
  3003. }
  3004. }
  3005. //
  3006. // First retrieve the currently active hardware profile ID, so we'll
  3007. // know what to look for when we're enumerating all profiles (only need
  3008. // to do this if the user wants the index of the currently active
  3009. // hardware profile).
  3010. //
  3011. if(CurrentlyActiveIndex) {
  3012. if((cr = CM_Get_Hardware_Profile_Info_Ex(0xFFFFFFFF, &HwProfInfo, 0, hMachine)) == CR_SUCCESS) {
  3013. //
  3014. // Store away the hardware profile ID.
  3015. //
  3016. CurHwProfile = HwProfInfo.HWPI_ulHWProfile;
  3017. } else {
  3018. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  3019. leave;
  3020. }
  3021. }
  3022. //
  3023. // Enumerate the hardware profiles, retrieving the ID for each.
  3024. //
  3025. i = 0;
  3026. do {
  3027. if((cr = CM_Get_Hardware_Profile_Info_Ex(i, &HwProfInfo, 0, hMachine)) == CR_SUCCESS) {
  3028. if(i < HwProfileListSize) {
  3029. HwProfileList[i] = HwProfInfo.HWPI_ulHWProfile;
  3030. }
  3031. if(CurrentlyActiveIndex && (HwProfInfo.HWPI_ulHWProfile == CurHwProfile)) {
  3032. *CurrentlyActiveIndex = i;
  3033. //
  3034. // Clear the CurrentlyActiveIndex pointer, so we once we find the
  3035. // currently active profile, we won't have to keep comparing.
  3036. //
  3037. CurrentlyActiveIndex = NULL;
  3038. }
  3039. i++;
  3040. }
  3041. } while(cr == CR_SUCCESS);
  3042. if(cr == CR_NO_MORE_HW_PROFILES) {
  3043. //
  3044. // Then we enumerated all hardware profiles. Now see if we had
  3045. // enough buffer to hold them all.
  3046. //
  3047. *RequiredSize = i;
  3048. if(i > HwProfileListSize) {
  3049. Err = ERROR_INSUFFICIENT_BUFFER;
  3050. }
  3051. } else {
  3052. //
  3053. // Something else happened (probably a key not present).
  3054. //
  3055. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  3056. }
  3057. } except(pSetupExceptionFilter(GetExceptionCode())) {
  3058. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  3059. }
  3060. if(hMachine) {
  3061. CM_Disconnect_Machine(hMachine);
  3062. }
  3063. SetLastError(Err);
  3064. return (Err == NO_ERROR);
  3065. }
  3066. DWORD
  3067. pSetupDiGetCoInstallerList(
  3068. IN HDEVINFO DeviceInfoSet, OPTIONAL
  3069. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  3070. IN CONST GUID *ClassGuid, OPTIONAL
  3071. IN OUT PDEVINSTALL_PARAM_BLOCK InstallParamBlock,
  3072. IN OUT PVERIFY_CONTEXT VerifyContext OPTIONAL
  3073. )
  3074. /*++
  3075. Routine Description:
  3076. This routine retrieves the list of co-installers (both class- and
  3077. device-specific) and stores the entry points and module handles in
  3078. the supplied install param block.
  3079. Arguments:
  3080. DeviceInfoSet - Supplies a handle to the device information set to retrieve
  3081. co-installers into. If DeviceInfoSet is not specified, then the
  3082. InstallParamBlock specified below will be that of the set itself.
  3083. DeviceInfoData - Optionally, specifies the device information element
  3084. for which a list of co-installers is to be retrieved.
  3085. ClassGuid - Optionally, supplies the address of the device setup class GUID
  3086. for which class-specific co-installers are to be retrieved.
  3087. InstallParamBlock - Supplies the address of the install param block where
  3088. the co-installer list is to be stored. This will either be the param
  3089. block of the set itself (if DeviceInfoData isn't specified), or of
  3090. the specified device information element.
  3091. VerifyContext - optionally, supplies the address of a structure that caches
  3092. various verification context handles. These handles may be NULL (if
  3093. not previously acquired, and they may be filled in upon return (in
  3094. either success or failure) if they were acquired during the processing
  3095. of this verification request. It is the caller's responsibility to
  3096. free these various context handles when they are no longer needed by
  3097. calling pSetupFreeVerifyContextMembers.
  3098. Return Value:
  3099. If the function succeeds, the return value is NO_ERROR, otherwise it is
  3100. a Win32 error code indicating the cause of failure.
  3101. --*/
  3102. {
  3103. HKEY hk[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  3104. DWORD Err, RegDataType, KeyIndex;
  3105. LONG i;
  3106. PTSTR CoInstallerBuffer;
  3107. DWORD CoInstallerBufferSize;
  3108. PTSTR CurEntry;
  3109. PCOINSTALLER_NODE CoInstallerList, TempCoInstallerList;
  3110. DWORD CoInstallerListSize;
  3111. TCHAR GuidString[GUID_STRING_LEN];
  3112. TCHAR DescBuffer[LINE_LEN];
  3113. PTSTR DeviceDesc;
  3114. HWND hwndParent;
  3115. BOOL MustAbort;
  3116. MYASSERT(sizeof(GuidString) == sizeof(pszGuidNull));
  3117. //
  3118. // If there is already a list, then return success immediately.
  3119. //
  3120. if(InstallParamBlock->CoInstallerCount != -1) {
  3121. return NO_ERROR;
  3122. }
  3123. //
  3124. // Retrieve the parent window handle, as we may need it below if we need to
  3125. // popup UI due to unsigned class-/co-installers.
  3126. //
  3127. if(hwndParent = InstallParamBlock->hwndParent) {
  3128. if(!IsWindow(hwndParent)) {
  3129. hwndParent = NULL;
  3130. }
  3131. }
  3132. //
  3133. // Retrieve a device description to use in case we need to give a driver
  3134. // signing warn/block popup.
  3135. //
  3136. if(GetBestDeviceDesc(DeviceInfoSet, DeviceInfoData, DescBuffer)) {
  3137. DeviceDesc = DescBuffer;
  3138. } else {
  3139. DeviceDesc = NULL;
  3140. }
  3141. //
  3142. // Get the string form of the class GUID, because that will be the name of
  3143. // the multisz value entry under HKLM\System\CCS\Control\CoDeviceInstallers
  3144. // where class-specific co-installers will be registered
  3145. //
  3146. if(ClassGuid) {
  3147. pSetupStringFromGuid(ClassGuid, GuidString, SIZECHARS(GuidString));
  3148. } else {
  3149. CopyMemory(GuidString, pszGuidNull, sizeof(pszGuidNull));
  3150. }
  3151. CoInstallerBuffer = NULL;
  3152. CoInstallerBufferSize = 256 * sizeof(TCHAR); // start out with 256-character buffer
  3153. CoInstallerList = NULL;
  3154. i = 0;
  3155. try {
  3156. //
  3157. // Open the CoDeviceInstallers key, as well as the device's driver key (if
  3158. // a devinfo element is specified).
  3159. //
  3160. Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3161. pszPathCoDeviceInstallers,
  3162. 0,
  3163. KEY_READ,
  3164. &(hk[0])
  3165. );
  3166. if(Err != ERROR_SUCCESS) {
  3167. hk[0] = INVALID_HANDLE_VALUE;
  3168. }
  3169. if(DeviceInfoData) {
  3170. hk[1] = SetupDiOpenDevRegKey(DeviceInfoSet,
  3171. DeviceInfoData,
  3172. DICS_FLAG_GLOBAL,
  3173. 0,
  3174. DIREG_DRV,
  3175. KEY_READ
  3176. );
  3177. } else {
  3178. hk[1] = INVALID_HANDLE_VALUE;
  3179. }
  3180. for(KeyIndex = 0; KeyIndex < 2; KeyIndex++) {
  3181. //
  3182. // If we couldn't open a key for this location, move on to the next
  3183. // one.
  3184. //
  3185. if(hk[KeyIndex] == INVALID_HANDLE_VALUE) {
  3186. continue;
  3187. }
  3188. //
  3189. // Retrieve the multi-sz value containing the co-installer entries.
  3190. //
  3191. while(TRUE) {
  3192. if(!CoInstallerBuffer) {
  3193. if(!(CoInstallerBuffer = MyMalloc(CoInstallerBufferSize))) {
  3194. Err = ERROR_NOT_ENOUGH_MEMORY;
  3195. break;
  3196. }
  3197. }
  3198. Err = RegQueryValueEx(hk[KeyIndex],
  3199. (KeyIndex ? pszCoInstallers32
  3200. : GuidString),
  3201. NULL,
  3202. &RegDataType,
  3203. (PBYTE)CoInstallerBuffer,
  3204. &CoInstallerBufferSize
  3205. );
  3206. if(Err == ERROR_MORE_DATA) {
  3207. //
  3208. // Buffer wasn't large enough--free current one and try again with new size.
  3209. //
  3210. MyFree(CoInstallerBuffer);
  3211. CoInstallerBuffer = NULL;
  3212. } else {
  3213. break;
  3214. }
  3215. }
  3216. //
  3217. // Only out-of-memory errors are treated as fatal here.
  3218. //
  3219. if(Err == ERROR_NOT_ENOUGH_MEMORY) {
  3220. leave;
  3221. } else if(Err == ERROR_SUCCESS) {
  3222. //
  3223. // Make sure the buffer we got back looks valid.
  3224. //
  3225. if((RegDataType != REG_MULTI_SZ) || (CoInstallerBufferSize < sizeof(TCHAR))) {
  3226. Err = ERROR_INVALID_COINSTALLER;
  3227. leave;
  3228. }
  3229. //
  3230. // Count the number of entries in this multi-sz list.
  3231. //
  3232. for(CoInstallerListSize = 0, CurEntry = CoInstallerBuffer;
  3233. *CurEntry;
  3234. CoInstallerListSize++, CurEntry += (lstrlen(CurEntry) + 1)
  3235. );
  3236. if(!CoInstallerListSize) {
  3237. //
  3238. // List is empty, move on to next one.
  3239. //
  3240. continue;
  3241. }
  3242. //
  3243. // Allocate (or reallocate) an array large enough to hold this
  3244. // many co-installer entries.
  3245. //
  3246. if(CoInstallerList) {
  3247. TempCoInstallerList = MyRealloc(CoInstallerList,
  3248. (CoInstallerListSize + i) * sizeof(COINSTALLER_NODE)
  3249. );
  3250. } else {
  3251. MYASSERT(i == 0);
  3252. TempCoInstallerList = MyMalloc(CoInstallerListSize * sizeof(COINSTALLER_NODE));
  3253. }
  3254. if(TempCoInstallerList) {
  3255. CoInstallerList = TempCoInstallerList;
  3256. } else {
  3257. Err = ERROR_NOT_ENOUGH_MEMORY;
  3258. leave;
  3259. }
  3260. //
  3261. // Now loop through the list and get the co-installer for each
  3262. // entry.
  3263. //
  3264. for(CurEntry = CoInstallerBuffer; *CurEntry; CurEntry += (lstrlen(CurEntry) + 1)) {
  3265. //
  3266. // Initialize the hinstance to NULL, so we'll know whether
  3267. // or not we need to free the module if we hit an exception
  3268. // here.
  3269. //
  3270. CoInstallerList[i].hinstCoInstaller = NULL;
  3271. Err = GetModuleEntryPoint(INVALID_HANDLE_VALUE,
  3272. CurEntry,
  3273. pszCoInstallerDefaultProc,
  3274. &(CoInstallerList[i].hinstCoInstaller),
  3275. &((FARPROC)CoInstallerList[i].CoInstallerEntryPoint),
  3276. &(CoInstallerList[i].CoInstallerFusionContext),
  3277. &MustAbort,
  3278. InstallParamBlock->LogContext,
  3279. hwndParent,
  3280. ClassGuid,
  3281. SetupapiVerifyCoInstProblem,
  3282. DeviceDesc,
  3283. DRIVERSIGN_NONE,
  3284. TRUE,
  3285. VerifyContext
  3286. );
  3287. if(Err == NO_ERROR) {
  3288. i++;
  3289. } else {
  3290. //
  3291. // If the error we encountered above causes us to abort
  3292. // (e.g., due to a driver signing problem), then get
  3293. // out now. Otherwise, just skip this failed entry and
  3294. // move on to the next.
  3295. //
  3296. if(MustAbort) {
  3297. leave;
  3298. }
  3299. }
  3300. }
  3301. }
  3302. if(CoInstallerBuffer) {
  3303. MyFree(CoInstallerBuffer);
  3304. CoInstallerBuffer = NULL;
  3305. }
  3306. }
  3307. //
  3308. // If we get to here then we've successfully retrieved the co-installer
  3309. // list(s)
  3310. //
  3311. Err = NO_ERROR;
  3312. } except(pSetupExceptionFilter(GetExceptionCode())) {
  3313. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_COINSTALLER, &Err);
  3314. }
  3315. if(CoInstallerBuffer) {
  3316. MyFree(CoInstallerBuffer);
  3317. }
  3318. for(KeyIndex = 0; KeyIndex < 2; KeyIndex++) {
  3319. if(hk[KeyIndex] != INVALID_HANDLE_VALUE) {
  3320. RegCloseKey(hk[KeyIndex]);
  3321. }
  3322. }
  3323. if(Err == NO_ERROR) {
  3324. InstallParamBlock->CoInstallerList = CoInstallerList;
  3325. InstallParamBlock->CoInstallerCount = i;
  3326. } else if(CoInstallerList) {
  3327. MyFree(CoInstallerList);
  3328. }
  3329. return Err;
  3330. }