Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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