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

1436 lines
49 KiB

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