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.

1474 lines
48 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: finish.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "hdwwiz.h"
  11. #include <help.h>
  12. HMODULE hSrClientDll;
  13. typedef
  14. BOOL
  15. (*SRSETRESTOREPOINT)(
  16. PRESTOREPOINTINFO pRestorePtSpec,
  17. PSTATEMGRSTATUS pSMgrStatus
  18. );
  19. BOOL
  20. DeviceHasResources(
  21. DEVINST DeviceInst
  22. )
  23. {
  24. CONFIGRET ConfigRet;
  25. ULONG lcType = NUM_LOG_CONF;
  26. while (lcType--) {
  27. ConfigRet = CM_Get_First_Log_Conf_Ex(NULL, DeviceInst, lcType, NULL);
  28. if (ConfigRet == CR_SUCCESS) {
  29. return TRUE;
  30. }
  31. }
  32. return FALSE;
  33. }
  34. DWORD
  35. HdwRemoveDevice(
  36. PHARDWAREWIZ HardwareWiz
  37. )
  38. {
  39. SP_REMOVEDEVICE_PARAMS RemoveDeviceParams;
  40. LONG Error = ERROR_SUCCESS;
  41. RemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  42. RemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
  43. RemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL;
  44. RemoveDeviceParams.HwProfile = 0;
  45. if (!SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo,
  46. &HardwareWiz->DeviceInfoData,
  47. (PSP_CLASSINSTALL_HEADER)&RemoveDeviceParams,
  48. sizeof(RemoveDeviceParams)
  49. )
  50. ||
  51. !SetupDiCallClassInstaller(DIF_REMOVE,
  52. HardwareWiz->hDeviceInfo,
  53. &HardwareWiz->DeviceInfoData
  54. )) {
  55. Error = GetLastError();
  56. }
  57. //
  58. // Clear the class install parameters.
  59. //
  60. SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo,
  61. &HardwareWiz->DeviceInfoData,
  62. NULL,
  63. 0
  64. );
  65. return Error;
  66. }
  67. BOOL
  68. GetClassGuidForInf(
  69. PTSTR InfFileName,
  70. LPGUID ClassGuid
  71. )
  72. {
  73. TCHAR ClassName[MAX_CLASS_NAME_LEN];
  74. DWORD NumGuids;
  75. if (!SetupDiGetINFClass(InfFileName,
  76. ClassGuid,
  77. ClassName,
  78. sizeof(ClassName)/sizeof(TCHAR),
  79. NULL)) {
  80. return FALSE;
  81. }
  82. if (IsEqualGUID(ClassGuid, &GUID_NULL)) {
  83. //
  84. // Then we need to retrieve the GUID associated with the INF's class name.
  85. // (If this class name isn't installed (i.e., has no corresponding GUID),
  86. // of if it matches with multiple GUIDs, then we abort.
  87. //
  88. if (!SetupDiClassGuidsFromName(ClassName, ClassGuid, 1, &NumGuids) ||
  89. !NumGuids) {
  90. return FALSE;
  91. }
  92. }
  93. return TRUE;
  94. }
  95. LONG
  96. ClassInstallerInstalls(
  97. HWND hwndParent,
  98. PHARDWAREWIZ HardwareWiz,
  99. HDEVINFO hDeviceInfo,
  100. PSP_DEVINFO_DATA DeviceInfoData,
  101. BOOL InstallFilesOnly
  102. )
  103. {
  104. DWORD Err = ERROR_SUCCESS;
  105. HSPFILEQ FileQueue = INVALID_HANDLE_VALUE;
  106. PVOID MessageHandlerContext = NULL;
  107. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  108. DWORD ScanResult = 0;
  109. RESTOREPOINTINFO RestorePointInfo;
  110. STATEMGRSTATUS SMgrStatus;
  111. int FileQueueNeedsReboot = 0;
  112. //
  113. // verify with class installer, and class-specific coinstallers
  114. // that the driver is not blacklisted. For DIF_ALLOW_INSTALL we
  115. // accept ERROR_SUCCESS or ERROR_DI_DO_DEFAULT as good return codes.
  116. //
  117. if (!SetupDiCallClassInstaller(DIF_ALLOW_INSTALL,
  118. hDeviceInfo,
  119. DeviceInfoData
  120. ) &&
  121. (GetLastError() != ERROR_DI_DO_DEFAULT)) {
  122. Err = GetLastError();
  123. goto clean0;
  124. }
  125. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  126. if (!SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  127. &HardwareWiz->DeviceInfoData,
  128. &DeviceInstallParams
  129. )) {
  130. Err = GetLastError();
  131. goto clean0;
  132. }
  133. FileQueue = SetupOpenFileQueue();
  134. if (FileQueue == INVALID_HANDLE_VALUE) {
  135. Err = ERROR_NOT_ENOUGH_MEMORY;
  136. goto clean0;
  137. }
  138. DeviceInstallParams.Flags |= DI_NOVCP;
  139. DeviceInstallParams.FileQueue = FileQueue;
  140. SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  141. &HardwareWiz->DeviceInfoData,
  142. &DeviceInstallParams
  143. );
  144. //
  145. // Set the SPQ_FLAG_ABORT_IF_UNSIGNED value on the file queue. With this
  146. // flag set setupapi will bail out of the copy if it encounters an unsigned
  147. // file. At that point we will set a system restore point and then
  148. // do the copy. This way the user can back out of an unsigned driver
  149. // install using system restore.
  150. //
  151. // Note that system restore is currently not supported on 64-bit so don't
  152. // bother setting the SPQ_FLAG_ABORT_IF_UNSIGNED.
  153. //
  154. #ifndef _WIN64
  155. SetupSetFileQueueFlags(FileQueue,
  156. SPQ_FLAG_ABORT_IF_UNSIGNED,
  157. SPQ_FLAG_ABORT_IF_UNSIGNED
  158. );
  159. #endif
  160. //
  161. // Install the files first in one shot.
  162. // This allows new coinstallers to run during the install.
  163. //
  164. if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
  165. hDeviceInfo,
  166. DeviceInfoData
  167. )) {
  168. Err = GetLastError();
  169. goto clean0;
  170. }
  171. //
  172. // Since we created our own FileQueue then we need to
  173. // scan and possibly commit the queue and prune copies as needed.
  174. //
  175. if (!SetupScanFileQueue(FileQueue,
  176. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  177. hwndParent,
  178. NULL,
  179. NULL,
  180. &ScanResult
  181. )) {
  182. //
  183. // If the API failed then set the ScanResult to 0 (failure).
  184. //
  185. ScanResult = 0;
  186. }
  187. //
  188. // If the ScanResult is 1 then that means that all of the files are present
  189. // and that there are no rename or delete operations are left in the copy
  190. // queue. This means we can skip the file queue commit.
  191. //
  192. // If the ScanResult is 0 then there are file copy operations that are needed.
  193. // If the ScanResult is 2 then there are delete, rename or backup operations
  194. // that are needed.
  195. //
  196. if (ScanResult != 1) {
  197. MessageHandlerContext = SetupInitDefaultQueueCallbackEx(
  198. hwndParent,
  199. (DeviceInstallParams.Flags & DI_QUIETINSTALL)
  200. ? INVALID_HANDLE_VALUE : NULL,
  201. 0,
  202. 0,
  203. NULL
  204. );
  205. if (MessageHandlerContext) {
  206. //
  207. // Commit the file queue.
  208. //
  209. if (!SetupCommitFileQueue(hwndParent,
  210. FileQueue,
  211. SetupDefaultQueueCallback,
  212. MessageHandlerContext
  213. )) {
  214. Err = GetLastError();
  215. if (Err == ERROR_SET_SYSTEM_RESTORE_POINT) {
  216. SetupTermDefaultQueueCallback(MessageHandlerContext);
  217. MessageHandlerContext = SetupInitDefaultQueueCallbackEx(
  218. hwndParent,
  219. (DeviceInstallParams.Flags & DI_QUIETINSTALL)
  220. ? INVALID_HANDLE_VALUE : NULL,
  221. 0,
  222. 0,
  223. NULL
  224. );
  225. if (MessageHandlerContext) {
  226. HMODULE hSrClientDll = NULL;
  227. SRSETRESTOREPOINT pfnSrSetRestorePoint = NULL;
  228. if (((hSrClientDll = LoadLibrary(TEXT("srclient.dll")))) &&
  229. ((pfnSrSetRestorePoint = (SRSETRESTOREPOINT)GetProcAddress(hSrClientDll,
  230. "SRSetRestorePointW"
  231. )))) {
  232. //
  233. // Set the system restore point.
  234. //
  235. RestorePointInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
  236. RestorePointInfo.dwRestorePtType = DEVICE_DRIVER_INSTALL;
  237. RestorePointInfo.llSequenceNumber = 0;
  238. if (!LoadString(hHdwWiz,
  239. IDS_NEW_SETRESTOREPOINT,
  240. RestorePointInfo.szDescription,
  241. SIZECHARS(RestorePointInfo.szDescription)
  242. )) {
  243. RestorePointInfo.szDescription[0] = TEXT('\0');
  244. }
  245. pfnSrSetRestorePoint(&RestorePointInfo, &SMgrStatus);
  246. FreeLibrary(hSrClientDll);
  247. }
  248. //
  249. // Clear the SPQ_FLAG_ABORT_IF_UNSIGNED flag so the file
  250. // queue will be commited the next time.
  251. //
  252. SetupSetFileQueueFlags(FileQueue,
  253. SPQ_FLAG_ABORT_IF_UNSIGNED,
  254. 0
  255. );
  256. //
  257. // Now that we have set the restore point and cleared the
  258. // SPQ_FLAG_ABORT_IF_UNSIGNED flag from the file queue we
  259. // can commit the queue again.
  260. //
  261. if (!SetupCommitFileQueue(hwndParent,
  262. FileQueue,
  263. SetupDefaultQueueCallback,
  264. MessageHandlerContext
  265. )) {
  266. Err = GetLastError();
  267. goto clean0;
  268. } else {
  269. //
  270. // We were successful in commiting the file queue, so check
  271. // to see whether a reboot is required as a result of committing
  272. // the queue (i.e. because files were in use, or the INF requested
  273. // a reboot).
  274. //
  275. FileQueueNeedsReboot = SetupPromptReboot(FileQueue, NULL, TRUE);
  276. }
  277. }
  278. } else {
  279. goto clean0;
  280. }
  281. } else {
  282. //
  283. // We were successful in commiting the file queue, so check
  284. // to see whether a reboot is required as a result of committing
  285. // the queue (i.e. because files were in use, or the INF requested
  286. // a reboot).
  287. //
  288. FileQueueNeedsReboot = SetupPromptReboot(FileQueue, NULL, TRUE);
  289. }
  290. }
  291. }
  292. //
  293. // If we were only copiny files then we are done!
  294. //
  295. if (InstallFilesOnly) {
  296. Err = ERROR_SUCCESS;
  297. goto clean0;
  298. }
  299. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  300. if (SetupDiGetDeviceInstallParams(hDeviceInfo,
  301. DeviceInfoData,
  302. &DeviceInstallParams
  303. )) {
  304. DWORD FileQueueFlags;
  305. //
  306. // If we didn't copy any files when commiting the file queue then the
  307. // SPQ_FLAG_FILES_MODIFIED flag will NOT be set. In this case set
  308. // the DI_FLAGSEX_RESTART_DEVICE_ONLY flag so that we only stop/start
  309. // this single device. By default setupapi will stop/start this device
  310. // as well as any other device that was using the same driver/filter
  311. // that this device is using.
  312. //
  313. if (SetupGetFileQueueFlags(FileQueue, &FileQueueFlags) &&
  314. !(FileQueueFlags & SPQ_FLAG_FILES_MODIFIED)) {
  315. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_RESTART_DEVICE_ONLY;
  316. }
  317. //
  318. // Set the DI_NOFILECOPY flag since we already copied the files during
  319. // the DIF_INSTALLDEVICEFILES, so we don't need to copy them again during
  320. // the DIF_INSTALLDEVICE.
  321. //
  322. DeviceInstallParams.Flags |= DI_NOFILECOPY;
  323. SetupDiSetDeviceInstallParams(hDeviceInfo,
  324. DeviceInfoData,
  325. &DeviceInstallParams
  326. );
  327. }
  328. //
  329. // Register any device-specific co-installers for this device,
  330. //
  331. if (!SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS,
  332. hDeviceInfo,
  333. DeviceInfoData
  334. )) {
  335. Err = GetLastError();
  336. goto clean0;
  337. }
  338. //
  339. // install any INF/class installer-specified interfaces.
  340. // and then finally the real "InstallDevice"!
  341. //
  342. if (!SetupDiCallClassInstaller(DIF_INSTALLINTERFACES,
  343. hDeviceInfo,
  344. DeviceInfoData
  345. )
  346. ||
  347. !SetupDiCallClassInstaller(DIF_INSTALLDEVICE,
  348. hDeviceInfo,
  349. DeviceInfoData
  350. )) {
  351. Err = GetLastError();
  352. goto clean0;
  353. }
  354. Err = ERROR_SUCCESS;
  355. clean0:
  356. if (MessageHandlerContext) {
  357. SetupTermDefaultQueueCallback(MessageHandlerContext);
  358. }
  359. //
  360. // If the file queue said that a reboot was needed then set the
  361. // DI_NEEDRESTART flag.
  362. //
  363. if (FileQueueNeedsReboot) {
  364. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  365. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  366. &HardwareWiz->DeviceInfoData,
  367. &DeviceInstallParams
  368. )) {
  369. DeviceInstallParams.Flags |= DI_NEEDRESTART;
  370. SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  371. &HardwareWiz->DeviceInfoData,
  372. &DeviceInstallParams
  373. );
  374. }
  375. }
  376. if (FileQueue != INVALID_HANDLE_VALUE) {
  377. //
  378. // If we have a valid file queue handle and there was an error during
  379. // the device install then we want to delete any new INFs that were
  380. // copied into the INF directory. We do this under the assumption that
  381. // since there was an error during the install these INFs must be bad.
  382. //
  383. if (Err != ERROR_SUCCESS) {
  384. SetupUninstallNewlyCopiedInfs(FileQueue,
  385. 0,
  386. NULL
  387. );
  388. }
  389. //
  390. // Clear out our file queue from the device install params. We need
  391. // to do this or else SetupCloseFileQueue will fail because it will
  392. // still have a ref count.
  393. //
  394. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  395. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  396. &HardwareWiz->DeviceInfoData,
  397. &DeviceInstallParams
  398. )) {
  399. DeviceInstallParams.Flags &= ~DI_NOVCP;
  400. DeviceInstallParams.FileQueue = INVALID_HANDLE_VALUE;
  401. SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  402. &HardwareWiz->DeviceInfoData,
  403. &DeviceInstallParams
  404. );
  405. }
  406. SetupCloseFileQueue(FileQueue);
  407. }
  408. return Err;
  409. }
  410. //
  411. // invokable only from finish page!
  412. //
  413. DWORD
  414. InstallDev(
  415. HWND hwndParent,
  416. PHARDWAREWIZ HardwareWiz
  417. )
  418. {
  419. SP_DRVINFO_DATA DriverInfoData;
  420. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  421. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  422. TCHAR ClassGuidString[MAX_GUID_STRING_LEN];
  423. GUID ClassGuidInf;
  424. LPGUID ClassGuid;
  425. int ClassGuidNum;
  426. DWORD Error = ERROR_SUCCESS;
  427. BOOL IgnoreRebootFlags = FALSE;
  428. TCHAR Buffer[MAX_PATH*2];
  429. PVOID pvBuffer = Buffer;
  430. ULONG DevNodeStatus = 0, Problem = 0;
  431. DWORD ClassGuidListSize, i;
  432. if (!HardwareWiz->ClassGuidSelected) {
  433. HardwareWiz->ClassGuidSelected = (LPGUID)&GUID_NULL;
  434. }
  435. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  436. if (SetupDiGetSelectedDriver(HardwareWiz->hDeviceInfo,
  437. &HardwareWiz->DeviceInfoData,
  438. &DriverInfoData
  439. )) {
  440. //
  441. // Get details on this driver node, so that we can examine the INF that this
  442. // node came from.
  443. //
  444. DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  445. if (!SetupDiGetDriverInfoDetail(HardwareWiz->hDeviceInfo,
  446. &HardwareWiz->DeviceInfoData,
  447. &DriverInfoData,
  448. &DriverInfoDetailData,
  449. sizeof(DriverInfoDetailData),
  450. NULL
  451. )) {
  452. Error = GetLastError();
  453. if (Error != ERROR_INSUFFICIENT_BUFFER) {
  454. goto clean0;
  455. }
  456. }
  457. //
  458. // Verif that the class is installed, if its not then
  459. // attempt to install it.
  460. //
  461. HdwBuildClassInfoList(HardwareWiz,
  462. 0,
  463. HardwareWiz->hMachine ? HardwareWiz->MachineName : NULL
  464. );
  465. //
  466. // fetch classguid from inf, (It may be different than what we already
  467. // have in class guid selected).
  468. //
  469. if (!GetClassGuidForInf(DriverInfoDetailData.InfFileName, &ClassGuidInf)) {
  470. ClassGuidInf = *HardwareWiz->ClassGuidSelected;
  471. }
  472. if (IsEqualGUID(&ClassGuidInf, &GUID_NULL)) {
  473. ClassGuidInf = GUID_DEVCLASS_UNKNOWN;
  474. }
  475. //
  476. // if the ClassGuidInf wasn't found then this class hasn't been installed yet.
  477. // -install the class installer now.
  478. //
  479. ClassGuid = HardwareWiz->ClassGuidList;
  480. ClassGuidNum = HardwareWiz->ClassGuidNum;
  481. while (ClassGuidNum--) {
  482. if (IsEqualGUID(ClassGuid, &ClassGuidInf)) {
  483. break;
  484. }
  485. ClassGuid++;
  486. }
  487. if (ClassGuidNum < 0 &&
  488. !SetupDiInstallClass(hwndParent,
  489. DriverInfoDetailData.InfFileName,
  490. 0,
  491. NULL
  492. )) {
  493. Error = GetLastError();
  494. goto clean0;
  495. }
  496. //
  497. // Now make sure that the class of this device is the same as the class
  498. // of the selected driver node.
  499. //
  500. if (!IsEqualGUID(&ClassGuidInf, HardwareWiz->ClassGuidSelected)) {
  501. pSetupStringFromGuid(&ClassGuidInf,
  502. ClassGuidString,
  503. sizeof(ClassGuidString)/sizeof(TCHAR)
  504. );
  505. SetupDiSetDeviceRegistryProperty(HardwareWiz->hDeviceInfo,
  506. &HardwareWiz->DeviceInfoData,
  507. SPDRP_CLASSGUID,
  508. (PBYTE)ClassGuidString,
  509. sizeof(ClassGuidString)
  510. );
  511. }
  512. }
  513. //
  514. // No selected driver, and no associated class--use "Unknown" class.
  515. //
  516. else {
  517. //
  518. // If the devnode is currently running 'raw', then remember this
  519. // fact so that we don't require a reboot later (NULL driver installation
  520. // isn't going to change anything).
  521. //
  522. if (CM_Get_DevNode_Status(&DevNodeStatus,
  523. &Problem,
  524. HardwareWiz->DeviceInfoData.DevInst,
  525. 0) == CR_SUCCESS) {
  526. if (!SetupDiGetDeviceRegistryProperty(HardwareWiz->hDeviceInfo,
  527. &HardwareWiz->DeviceInfoData,
  528. SPDRP_SERVICE,
  529. NULL, // regdatatype
  530. pvBuffer,
  531. sizeof(Buffer),
  532. NULL
  533. )) {
  534. *Buffer = TEXT('\0');
  535. }
  536. if ((DevNodeStatus & DN_STARTED) && (*Buffer == TEXT('\0'))) {
  537. IgnoreRebootFlags = TRUE;
  538. }
  539. }
  540. if (IsEqualGUID(HardwareWiz->ClassGuidSelected, &GUID_NULL)) {
  541. pSetupStringFromGuid(&GUID_DEVCLASS_UNKNOWN,
  542. ClassGuidString,
  543. sizeof(ClassGuidString)/sizeof(TCHAR)
  544. );
  545. SetupDiSetDeviceRegistryProperty(HardwareWiz->hDeviceInfo,
  546. &HardwareWiz->DeviceInfoData,
  547. SPDRP_CLASSGUID,
  548. (PBYTE)ClassGuidString,
  549. sizeof(ClassGuidString)
  550. );
  551. }
  552. }
  553. //
  554. // since this is a legacy install, set the manually installed bit if the
  555. // driver that was selected was not a PnP driver.
  556. //
  557. if (!HardwareWiz->PnpDevice) {
  558. ULONG Len;
  559. CONFIGRET ConfigRet;
  560. ULONG ConfigFlag;
  561. Len = sizeof(ConfigFlag);
  562. ConfigRet = CM_Get_DevNode_Registry_Property_Ex(HardwareWiz->DeviceInfoData.DevInst,
  563. CM_DRP_CONFIGFLAGS,
  564. NULL,
  565. (PVOID)&ConfigFlag,
  566. &Len,
  567. 0,
  568. NULL
  569. );
  570. if (ConfigRet != CR_SUCCESS) {
  571. ConfigFlag = 0;
  572. }
  573. ConfigFlag |= CONFIGFLAG_MANUAL_INSTALL;
  574. CM_Set_DevNode_Registry_Property_Ex(HardwareWiz->DeviceInfoData.DevInst,
  575. CM_DRP_CONFIGFLAGS,
  576. (PVOID)&ConfigFlag,
  577. sizeof(ConfigFlag),
  578. 0,
  579. NULL
  580. );
  581. }
  582. Error = ClassInstallerInstalls(hwndParent,
  583. HardwareWiz,
  584. HardwareWiz->hDeviceInfo,
  585. &HardwareWiz->DeviceInfoData,
  586. HardwareWiz->PnpDevice
  587. );
  588. if (Error != ERROR_SUCCESS) {
  589. //
  590. // we Have an install error, including a user cancel.
  591. // Install the null driver.
  592. //
  593. if (SetupDiSetSelectedDriver(HardwareWiz->hDeviceInfo,
  594. &HardwareWiz->DeviceInfoData,
  595. NULL
  596. )) {
  597. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  598. &HardwareWiz->DeviceInfoData,
  599. &DeviceInstallParams
  600. )) {
  601. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_SETFAILEDINSTALL;
  602. SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  603. &HardwareWiz->DeviceInfoData,
  604. &DeviceInstallParams
  605. );
  606. }
  607. SetupDiInstallDevice(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData);
  608. }
  609. goto clean0;
  610. }
  611. //
  612. // Fetch the latest DeviceInstallParams for the restart bits.
  613. //
  614. if (!IgnoreRebootFlags) {
  615. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  616. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  617. &HardwareWiz->DeviceInfoData,
  618. &DeviceInstallParams
  619. )) {
  620. if (DeviceInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) {
  621. HardwareWiz->Reboot |= DI_NEEDREBOOT;
  622. }
  623. }
  624. }
  625. clean0:
  626. return Error;
  627. }
  628. DWORD
  629. InstallNullDriver(
  630. HWND hDlg,
  631. PHARDWAREWIZ HardwareWiz,
  632. BOOL FailedInstall
  633. )
  634. {
  635. SP_DEVINSTALL_PARAMS DevInstallParams;
  636. DWORD Status = ERROR_SUCCESS;
  637. DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  638. if (FailedInstall) {
  639. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  640. &HardwareWiz->DeviceInfoData,
  641. &DevInstallParams
  642. )) {
  643. DevInstallParams.FlagsEx |= DI_FLAGSEX_SETFAILEDINSTALL;
  644. SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  645. &HardwareWiz->DeviceInfoData,
  646. &DevInstallParams
  647. );
  648. }
  649. }
  650. if (SetupDiSetSelectedDriver(HardwareWiz->hDeviceInfo,
  651. &HardwareWiz->DeviceInfoData,
  652. NULL
  653. )) {
  654. Status = InstallDev(hDlg, HardwareWiz);
  655. }
  656. return Status;
  657. } // InstallNullDriver
  658. BOOL
  659. CALLBACK
  660. AddPropSheetPageProc(
  661. IN HPROPSHEETPAGE hpage,
  662. IN LPARAM lParam
  663. )
  664. {
  665. *((HPROPSHEETPAGE *)lParam) = hpage;
  666. return TRUE;
  667. }
  668. void
  669. DisplayResource(
  670. PHARDWAREWIZ HardwareWiz,
  671. HWND hWndParent,
  672. BOOL NeedsForcedConfig
  673. )
  674. {
  675. HINSTANCE hLib;
  676. PROPSHEETHEADER psh;
  677. HPROPSHEETPAGE hpsPages[1];
  678. SP_PROPSHEETPAGE_REQUEST PropPageRequest;
  679. LPFNADDPROPSHEETPAGES ExtensionPropSheetPage = NULL;
  680. SP_DEVINSTALL_PARAMS DevInstallParams;
  681. //
  682. // Now get the resource selection page from setupapi.dll
  683. //
  684. hLib = GetModuleHandle(TEXT("setupapi.dll"));
  685. if (hLib) {
  686. ExtensionPropSheetPage = (PVOID)GetProcAddress(hLib, "ExtensionPropSheetPageProc");
  687. }
  688. if (!ExtensionPropSheetPage) {
  689. return;
  690. }
  691. PropPageRequest.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
  692. PropPageRequest.PageRequested = SPPSR_SELECT_DEVICE_RESOURCES;
  693. PropPageRequest.DeviceInfoSet = HardwareWiz->hDeviceInfo;
  694. PropPageRequest.DeviceInfoData = &HardwareWiz->DeviceInfoData;
  695. if (!ExtensionPropSheetPage(&PropPageRequest,
  696. AddPropSheetPageProc,
  697. (LONG_PTR)hpsPages
  698. )) {
  699. // warning ?
  700. return;
  701. }
  702. //
  703. // create the property sheet
  704. //
  705. psh.dwSize = sizeof(PROPSHEETHEADER);
  706. psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
  707. psh.hwndParent = hWndParent;
  708. psh.hInstance = hHdwWiz;
  709. psh.pszIcon = NULL;
  710. psh.pszCaption = (LPTSTR)IDS_ADDNEWDEVICE;
  711. psh.nPages = 1;
  712. psh.phpage = hpsPages;
  713. psh.nStartPage = 0;
  714. psh.pfnCallback = NULL;
  715. //
  716. // Clear the Propchange pending bit in the DeviceInstall params.
  717. //
  718. DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  719. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  720. &HardwareWiz->DeviceInfoData,
  721. &DevInstallParams
  722. )) {
  723. DevInstallParams.FlagsEx &= ~DI_FLAGSEX_PROPCHANGE_PENDING;
  724. SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  725. &HardwareWiz->DeviceInfoData,
  726. &DevInstallParams
  727. );
  728. }
  729. //
  730. // Set the CONFIGFLAG_NEEDS_FORCED_CONFIG if this device needs a forced config.
  731. //
  732. if (NeedsForcedConfig) {
  733. DWORD ConfigFlags = 0;
  734. ULONG ulSize = sizeof(ConfigFlags);
  735. if (CM_Get_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst,
  736. CM_DRP_CONFIGFLAGS,
  737. NULL,
  738. (LPBYTE)&ConfigFlags,
  739. &ulSize,
  740. 0) != CR_SUCCESS) {
  741. ConfigFlags = 0;
  742. }
  743. ConfigFlags |= CONFIGFLAG_NEEDS_FORCED_CONFIG;
  744. CM_Set_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst,
  745. CM_DRP_CONFIGFLAGS,
  746. (LPBYTE)&ConfigFlags,
  747. sizeof(ConfigFlags),
  748. 0
  749. );
  750. }
  751. if (PropertySheet(&psh) == -1) {
  752. DestroyPropertySheetPage(hpsPages[0]);
  753. }
  754. //
  755. // If a PropChange occurred invoke the DIF_PROPERTYCHANGE
  756. //
  757. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  758. &HardwareWiz->DeviceInfoData,
  759. &DevInstallParams
  760. )) {
  761. if (DevInstallParams.FlagsEx & DI_FLAGSEX_PROPCHANGE_PENDING) {
  762. SP_PROPCHANGE_PARAMS PropChangeParams;
  763. PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  764. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  765. PropChangeParams.Scope = DICS_FLAG_GLOBAL;
  766. PropChangeParams.HwProfile = 0;
  767. if (SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo,
  768. &HardwareWiz->DeviceInfoData,
  769. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  770. sizeof(PropChangeParams)
  771. )) {
  772. SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
  773. HardwareWiz->hDeviceInfo,
  774. &HardwareWiz->DeviceInfoData
  775. );
  776. }
  777. //
  778. // Clear the class install parameters.
  779. //
  780. SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo,
  781. &HardwareWiz->DeviceInfoData,
  782. NULL,
  783. 0
  784. );
  785. }
  786. }
  787. //
  788. // See if we need to reboot
  789. //
  790. if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo,
  791. &HardwareWiz->DeviceInfoData,
  792. &DevInstallParams
  793. )) {
  794. if (DevInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) {
  795. HardwareWiz->Reboot |= DI_NEEDREBOOT;
  796. }
  797. }
  798. //
  799. // Clear the CONFIGFLAG_NEEDS_FORCED_CONFIG if this device needs a forced config.
  800. //
  801. if (NeedsForcedConfig) {
  802. DWORD ConfigFlags = 0;
  803. ULONG ulSize = sizeof(ConfigFlags);
  804. if (CM_Get_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst,
  805. CM_DRP_CONFIGFLAGS,
  806. NULL,
  807. (LPBYTE)&ConfigFlags,
  808. &ulSize,
  809. 0) == CR_SUCCESS) {
  810. ConfigFlags &= ~CONFIGFLAG_NEEDS_FORCED_CONFIG;
  811. CM_Set_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst,
  812. CM_DRP_CONFIGFLAGS,
  813. (LPBYTE)&ConfigFlags,
  814. sizeof(ConfigFlags),
  815. 0
  816. );
  817. }
  818. }
  819. return;
  820. }
  821. INT_PTR CALLBACK
  822. HdwInstallDevDlgProc(
  823. HWND hDlg,
  824. UINT wMsg,
  825. WPARAM wParam,
  826. LPARAM lParam
  827. )
  828. {
  829. HWND hwndParentDlg = GetParent(hDlg);
  830. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  831. LONG Error;
  832. ULONG DevNodeStatus, Problem;
  833. switch (wMsg) {
  834. case WM_INITDIALOG: {
  835. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  836. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  837. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  838. break;
  839. }
  840. case WM_DESTROY:
  841. break;
  842. case WUM_DOINSTALL:
  843. // do the Install
  844. HardwareWiz->LastError = InstallDev(hDlg, HardwareWiz);
  845. HardwareWiz->InstallPending = FALSE;
  846. HardwareWiz->CurrCursor = NULL;
  847. PropSheet_PressButton(hwndParentDlg, PSBTN_NEXT);
  848. break;
  849. case WM_NOTIFY:
  850. switch (((NMHDR FAR *)lParam)->code) {
  851. case PSN_SETACTIVE: {
  852. HICON hicon;
  853. SP_DRVINFO_DATA DriverInfoData;
  854. HardwareWiz->PrevPage = IDD_ADDDEVICE_INSTALLDEV;
  855. //
  856. // This is an intermediary status page, no buttons needed.
  857. // Set the device description
  858. // Set the class Icon
  859. //
  860. PropSheet_SetWizButtons(hwndParentDlg, 0);
  861. EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
  862. SetDriverDescription(hDlg, IDC_HDW_DESCRIPTION, HardwareWiz);
  863. if (SetupDiLoadClassIcon(HardwareWiz->ClassGuidSelected, &hicon, NULL)) {
  864. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  865. if (hicon) {
  866. DestroyIcon(hicon);
  867. }
  868. }
  869. HardwareWiz->CurrCursor = HardwareWiz->IdcWait;
  870. SetCursor(HardwareWiz->CurrCursor);
  871. //
  872. // Post ourselves a msg, to do the actual install, this allows this
  873. // page to show itself while the install is actually occuring.
  874. //
  875. HardwareWiz->InstallPending = TRUE;
  876. PostMessage(hDlg, WUM_DOINSTALL, 0, 0);
  877. break;
  878. }
  879. case PSN_WIZNEXT:
  880. //
  881. // Add the FinishInstall Page and jump to it if the installation succeded.
  882. //
  883. if (HardwareWiz->LastError == ERROR_SUCCESS) {
  884. HardwareWiz->WizExtFinishInstall.hPropSheet = CreateWizExtPage(IDD_WIZARDEXT_FINISHINSTALL,
  885. WizExtFinishInstallDlgProc,
  886. HardwareWiz
  887. );
  888. if (HardwareWiz->WizExtFinishInstall.hPropSheet) {
  889. PropSheet_AddPage(hwndParentDlg, HardwareWiz->WizExtFinishInstall.hPropSheet);
  890. }
  891. SetDlgMsgResult(hDlg, wMsg, IDD_WIZARDEXT_FINISHINSTALL);
  892. //
  893. // There was an error during the installation so just jump to our finish page.
  894. //
  895. } else {
  896. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_FINISH);
  897. }
  898. break;
  899. }
  900. break;
  901. case WM_SETCURSOR:
  902. if (HardwareWiz->CurrCursor) {
  903. SetCursor(HardwareWiz->CurrCursor);
  904. break;
  905. }
  906. // fall thru to return(FALSE);
  907. default:
  908. return(FALSE);
  909. }
  910. return(TRUE);
  911. }
  912. void
  913. ShowInstallSummary(
  914. HWND hDlg,
  915. PHARDWAREWIZ HardwareWiz
  916. )
  917. {
  918. LONG Error;
  919. CONFIGRET ConfigRet;
  920. ULONG Len, Problem, DevNodeStatus;
  921. BOOL HasResources;
  922. HWND hwndParentDlg = GetParent(hDlg);
  923. PTCHAR ErrorMsg, ProblemText;
  924. TCHAR TextBuffer[MAX_PATH*4];
  925. Problem = 0;
  926. *TextBuffer = TEXT('\0');
  927. Error = HardwareWiz->LastError;
  928. //
  929. // Installation was canceled
  930. //
  931. if (Error == ERROR_CANCELLED) {
  932. PropSheet_PressButton(hwndParentDlg, PSBTN_CANCEL);
  933. return;
  934. }
  935. //
  936. // Installation failed
  937. //
  938. if (Error != ERROR_SUCCESS) {
  939. HardwareWiz->Installed = FALSE;
  940. LoadText(TextBuffer, sizeof(TextBuffer), IDS_HDW_ERRORFIN1, IDS_HDW_ERRORFIN1);
  941. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  942. NULL,
  943. HRESULT_FROM_SETUPAPI(Error),
  944. 0,
  945. (LPTSTR)&ErrorMsg,
  946. 0,
  947. NULL
  948. )) {
  949. lstrcat(TextBuffer, TEXT("\n\n"));
  950. lstrcat(TextBuffer, ErrorMsg);
  951. LocalFree(ErrorMsg);
  952. }
  953. SetDlgItemText(hDlg, IDC_HDW_TEXT, TextBuffer);
  954. }
  955. //
  956. // No errors installing the drivers for this device
  957. //
  958. else {
  959. //
  960. // Check to see if the device itself has any problems
  961. //
  962. Error = CM_Get_DevNode_Status(&DevNodeStatus,
  963. &Problem,
  964. HardwareWiz->DeviceInfoData.DevInst,
  965. 0
  966. );
  967. if (Error != CR_SUCCESS) {
  968. //
  969. // For some reason, we couldn't retrieve the devnode's status.
  970. // Default status and problem values to zero.
  971. //
  972. DevNodeStatus = Problem = 0;
  973. }
  974. //
  975. // make sure the reboot flags\Problem are set correctly
  976. //
  977. if (HardwareWiz->PnpDevice || HardwareWiz->Reboot || Problem == CM_PROB_NEED_RESTART ) {
  978. if (Problem != CM_PROB_PARTIAL_LOG_CONF) {
  979. Problem = CM_PROB_NEED_RESTART;
  980. }
  981. HardwareWiz->Reboot |= DI_NEEDREBOOT;
  982. }
  983. HardwareWiz->Installed = TRUE;
  984. HasResources = DeviceHasResources(HardwareWiz->DeviceInfoData.DevInst);
  985. //
  986. // The device has a problem
  987. //
  988. if ((Error != CR_SUCCESS) || Problem) {
  989. if (Problem == CM_PROB_NEED_RESTART) {
  990. if (HasResources &&
  991. !HardwareWiz->PnpDevice) {
  992. LoadText(TextBuffer, sizeof(TextBuffer), IDS_HDW_NORMAL_LEGACY_FINISH1, IDS_HDW_NORMAL_LEGACY_FINISH1);
  993. } else {
  994. LoadText(TextBuffer, sizeof(TextBuffer), IDS_HDW_NORMALFINISH1, IDS_HDW_NORMALFINISH1);
  995. }
  996. LoadText(TextBuffer, sizeof(TextBuffer), IDS_NEEDREBOOT, IDS_NEEDREBOOT);
  997. }
  998. else {
  999. LoadText(TextBuffer, sizeof(TextBuffer), IDS_INSTALL_PROBLEM, IDS_INSTALL_PROBLEM);
  1000. if (Problem) {
  1001. ProblemText = DeviceProblemText(NULL,
  1002. HardwareWiz->DeviceInfoData.DevInst,
  1003. 0,
  1004. Problem
  1005. );
  1006. if (ProblemText) {
  1007. lstrcat(TextBuffer, TEXT("\n\n"));
  1008. lstrcat(TextBuffer, ProblemText);
  1009. LocalFree(ProblemText);
  1010. }
  1011. }
  1012. }
  1013. //
  1014. // Show the resource button if the device has resources and it has a problem
  1015. //
  1016. if (HasResources ||
  1017. (Problem && !(HardwareWiz->Reboot && (DevNodeStatus & DN_STARTED))) ||
  1018. (Problem == CM_PROB_PARTIAL_LOG_CONF)) {
  1019. ShowWindow(GetDlgItem(hDlg, IDC_HDW_DISPLAYRESOURCE), SW_SHOW);
  1020. }
  1021. }
  1022. //
  1023. // Installation was sucessful and the device does not have any problems
  1024. //
  1025. else {
  1026. LoadText(TextBuffer, sizeof(TextBuffer), IDS_HDW_NORMALFINISH1, IDS_HDW_NORMALFINISH1);
  1027. }
  1028. SetDlgItemText(hDlg, IDC_HDW_TEXT, TextBuffer);
  1029. }
  1030. }
  1031. INT_PTR CALLBACK
  1032. HdwAddDeviceFinishDlgProc(
  1033. HWND hDlg,
  1034. UINT wMsg,
  1035. WPARAM wParam,
  1036. LPARAM lParam
  1037. )
  1038. {
  1039. HICON hicon;
  1040. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  1041. switch (wMsg) {
  1042. case WM_INITDIALOG:
  1043. {
  1044. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  1045. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  1046. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  1047. SetWindowFont(GetDlgItem(hDlg, IDC_HDWNAME), HardwareWiz->hfontTextBigBold, TRUE);
  1048. break;
  1049. }
  1050. case WM_DESTROY:
  1051. hicon = (HICON)LOWORD(SendDlgItemMessage(hDlg,IDC_CLASSICON,STM_GETICON,0,0));
  1052. if (hicon) {
  1053. DestroyIcon(hicon);
  1054. }
  1055. break;
  1056. case WM_NOTIFY:
  1057. switch (((NMHDR FAR *)lParam)->code) {
  1058. case PSN_SETACTIVE:
  1059. //
  1060. // No back button since install is already done.
  1061. // set the device description
  1062. // Hide Resources button until we know if resources exist or not.
  1063. // Set the class Icon
  1064. //
  1065. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
  1066. SetDriverDescription(hDlg, IDC_HDW_DESCRIPTION, HardwareWiz);
  1067. ShowWindow(GetDlgItem(hDlg, IDC_HDW_DISPLAYRESOURCE), SW_HIDE);
  1068. //
  1069. // Set the class Icon
  1070. //
  1071. if (SetupDiLoadClassIcon(&HardwareWiz->DeviceInfoData.ClassGuid, &hicon, NULL)) {
  1072. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  1073. if (hicon) {
  1074. DestroyIcon(hicon);
  1075. }
  1076. }
  1077. ShowInstallSummary(hDlg, HardwareWiz);
  1078. break;
  1079. case PSN_RESET:
  1080. //
  1081. // Cancel the install
  1082. //
  1083. if (HardwareWiz->Registered) {
  1084. HardwareWiz->Installed = FALSE;
  1085. }
  1086. break;
  1087. case PSN_WIZFINISH:
  1088. //
  1089. // Pnp Device install only consists of copying files
  1090. // when the system does the real install, it will create
  1091. // the proper devnode, so remove our temporary devnode.
  1092. //
  1093. if (HardwareWiz->PnpDevice && HardwareWiz->Registered) {
  1094. HardwareWiz->Installed = FALSE;
  1095. break;
  1096. }
  1097. break;
  1098. case NM_RETURN:
  1099. case NM_CLICK:
  1100. DisplayResource(HardwareWiz, GetParent(hDlg), FALSE);
  1101. break;
  1102. }
  1103. break;
  1104. default:
  1105. return(FALSE);
  1106. }
  1107. return(TRUE);
  1108. }
  1109. INT_PTR CALLBACK
  1110. WizExtFinishInstallDlgProc(
  1111. HWND hDlg,
  1112. UINT wMsg,
  1113. WPARAM wParam,
  1114. LPARAM lParam
  1115. )
  1116. {
  1117. HWND hwndParentDlg = GetParent(hDlg);
  1118. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  1119. int PrevPageId;
  1120. switch (wMsg) {
  1121. case WM_INITDIALOG: {
  1122. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  1123. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  1124. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  1125. break;
  1126. }
  1127. case WM_DESTROY:
  1128. break;
  1129. case WM_NOTIFY:
  1130. switch (((NMHDR FAR *)lParam)->code) {
  1131. case PSN_SETACTIVE:
  1132. PrevPageId = HardwareWiz->PrevPage;
  1133. HardwareWiz->PrevPage = IDD_WIZARDEXT_FINISHINSTALL;
  1134. if (PrevPageId == IDD_ADDDEVICE_INSTALLDEV) {
  1135. //
  1136. // Moving forward on first page
  1137. //
  1138. //
  1139. // Add ClassWizard Extension pages for FinishInstall
  1140. //
  1141. AddClassWizExtPages(hwndParentDlg,
  1142. HardwareWiz,
  1143. &HardwareWiz->WizExtFinishInstall.DeviceWizardData,
  1144. DIF_NEWDEVICEWIZARD_FINISHINSTALL
  1145. );
  1146. //
  1147. // Add the end page, which is FinishInstall end
  1148. //
  1149. HardwareWiz->WizExtFinishInstall.hPropSheetEnd = CreateWizExtPage(IDD_WIZARDEXT_FINISHINSTALL_END,
  1150. WizExtFinishInstallEndDlgProc,
  1151. HardwareWiz
  1152. );
  1153. if (HardwareWiz->WizExtFinishInstall.hPropSheetEnd) {
  1154. PropSheet_AddPage(hwndParentDlg, HardwareWiz->WizExtFinishInstall.hPropSheetEnd);
  1155. }
  1156. }
  1157. //
  1158. // We can't go backwards, so always go forward
  1159. //
  1160. SetDlgMsgResult(hDlg, wMsg, -1);
  1161. break;
  1162. case PSN_WIZNEXT:
  1163. SetDlgMsgResult(hDlg, wMsg, 0);
  1164. break;
  1165. }
  1166. break;
  1167. default:
  1168. return(FALSE);
  1169. }
  1170. return(TRUE);
  1171. }
  1172. INT_PTR CALLBACK
  1173. WizExtFinishInstallEndDlgProc(
  1174. HWND hDlg,
  1175. UINT wMsg,
  1176. WPARAM wParam,
  1177. LPARAM lParam
  1178. )
  1179. {
  1180. HWND hwndParentDlg = GetParent(hDlg);
  1181. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  1182. int PrevPageId;
  1183. switch (wMsg) {
  1184. case WM_INITDIALOG: {
  1185. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  1186. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  1187. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  1188. break;
  1189. }
  1190. case WM_DESTROY:
  1191. break;
  1192. case WM_NOTIFY:
  1193. switch (((NMHDR FAR *)lParam)->code) {
  1194. case PSN_SETACTIVE:
  1195. PrevPageId = HardwareWiz->PrevPage;
  1196. HardwareWiz->PrevPage = IDD_WIZARDEXT_FINISHINSTALL_END;
  1197. //
  1198. // We can't go backwards, so always go forward
  1199. //
  1200. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_FINISH);
  1201. break;
  1202. case PSN_WIZBACK:
  1203. case PSN_WIZNEXT:
  1204. SetDlgMsgResult(hDlg, wMsg, 0);
  1205. break;
  1206. }
  1207. break;
  1208. default:
  1209. return(FALSE);
  1210. }
  1211. return(TRUE);
  1212. }