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.

853 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: newdev.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "newdevp.h"
  11. #include <initguid.h>
  12. //
  13. // Define and initialize all device class GUIDs.
  14. // (This must only be done once per module!)
  15. //
  16. #include <devguid.h>
  17. //
  18. // Define and initialize a global variable, GUID_NULL
  19. // (from coguid.h)
  20. //
  21. DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  22. typedef
  23. BOOL
  24. (*PINSTALLNEWDEVICE)(
  25. HWND hwndParent,
  26. LPGUID ClassGuid,
  27. PDWORD pReboot
  28. );
  29. WNDPROC g_OldWizardProc;
  30. PINSTALLNEWDEVICE pInstallNewDevice = NULL;
  31. int g_BlankIconIndex;
  32. typedef struct _NewDevWizPropertySheet {
  33. PROPSHEETHEADER PropSheetHeader;
  34. HPROPSHEETPAGE PropSheetPages[16];
  35. } NDWPROPERTYSHEET, *PNDWPROPERTYSHEET;
  36. LRESULT CALLBACK
  37. WizParentWindowProc(
  38. HWND hwnd,
  39. UINT uMsg,
  40. WPARAM wParam,
  41. LPARAM lParam
  42. )
  43. /*++
  44. Routine Description:
  45. This function disables auto-run when the Found New Hardware Wizard is running.
  46. It is a subclass of the wizard's main window.
  47. Arguments:
  48. hwnd -
  49. uMsg -
  50. wParam -
  51. lParam -
  52. Return Value:
  53. If the message is QueryCancelAutoPlay then return TRUE to cancel AutoPlay,
  54. otherwise return the default window value.
  55. --*/
  56. {
  57. static UINT msgQueryCancelAutoPlay = 0;
  58. if (!msgQueryCancelAutoPlay) {
  59. msgQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  60. }
  61. if (uMsg == msgQueryCancelAutoPlay) {
  62. //
  63. // Cancel Auto-Play when the wizard is running.
  64. //
  65. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
  66. return 1;
  67. } else {
  68. return CallWindowProc(g_OldWizardProc, hwnd, uMsg, wParam, lParam);
  69. }
  70. }
  71. INT CALLBACK
  72. iNDWDlgCallback(
  73. IN HWND hwndDlg,
  74. IN UINT uMsg,
  75. IN LPARAM lParam
  76. )
  77. /*++
  78. Routine Description:
  79. Call back used to remove the "?" from the wizard page.
  80. Also used to subclass the wizard's window to catch the
  81. QueryCancelAutoRun message sent by the shell when an AutoRun
  82. CD is inserted.
  83. Arguments:
  84. hwndDlg - Handle to the property sheet dialog box.
  85. uMsg - Identifies the message being received. This parameter
  86. is one of the following values:
  87. PSCB_INITIALIZED - Indicates that the property sheet is
  88. being initialized. The lParam value is zero for this message.
  89. PSCB_PRECREATE Indicates that the property sheet is about
  90. to be created. The hwndDlg parameter is NULL and the lParam
  91. parameter is a pointer to a dialog template in memory. This
  92. template is in the form of a DLGTEMPLATE structure followed
  93. by one or more DLGITEMTEMPLATE structures.
  94. lParam - Specifies additional information about the message. The
  95. meaning of this value depends on the uMsg parameter.
  96. Return Value:
  97. The function returns zero.
  98. --*/
  99. {
  100. switch( uMsg ) {
  101. case PSCB_INITIALIZED:
  102. g_OldWizardProc = (WNDPROC)SetWindowLongPtr(hwndDlg,
  103. DWLP_DLGPROC,
  104. (LONG_PTR)WizParentWindowProc
  105. );
  106. break;
  107. case PSCB_PRECREATE:
  108. if( lParam ){
  109. //
  110. // This is done to hide the X and ? at the top of the wizard
  111. //
  112. DLGTEMPLATE *pDlgTemplate = (DLGTEMPLATE *)lParam;
  113. pDlgTemplate->style &= ~(DS_CONTEXTHELP | WS_SYSMENU);
  114. }
  115. break;
  116. }
  117. return FALSE;
  118. }
  119. PNDWPROPERTYSHEET
  120. InitNDWPropSheet(
  121. HWND hwndParent,
  122. PNEWDEVWIZ NewDevWiz,
  123. int StartPageId
  124. )
  125. {
  126. PNDWPROPERTYSHEET NdwPropertySheet;
  127. LPPROPSHEETHEADER PropSheetHeader;
  128. PROPSHEETPAGE psp;
  129. LPTSTR Title;
  130. //
  131. // Allocate memory for the header and the page array.
  132. //
  133. NdwPropertySheet = LocalAlloc(LPTR, sizeof(NDWPROPERTYSHEET));
  134. if (!NdwPropertySheet) {
  135. NewDevWiz->LastError = ERROR_NOT_ENOUGH_MEMORY;
  136. return NULL;
  137. }
  138. NewDevWiz->LastError = NdwBuildClassInfoList(NewDevWiz, DIBCI_NOINSTALLCLASS);
  139. if (NewDevWiz->LastError != ERROR_SUCCESS) {
  140. return NULL;
  141. }
  142. //
  143. // Initialize the PropertySheet Header
  144. //
  145. PropSheetHeader = &(NdwPropertySheet->PropSheetHeader);
  146. PropSheetHeader->dwSize = sizeof(NdwPropertySheet->PropSheetHeader);
  147. PropSheetHeader->dwFlags = PSH_WIZARD | PSH_USECALLBACK | PSH_WIZARD97 | PSH_WATERMARK | PSH_STRETCHWATERMARK | PSH_HEADER;
  148. PropSheetHeader->pszbmWatermark = MAKEINTRESOURCE(IDB_WATERBMP);
  149. PropSheetHeader->pszbmHeader = MAKEINTRESOURCE(IDB_BANNERBMP);
  150. PropSheetHeader->hwndParent = hwndParent;
  151. PropSheetHeader->hInstance = hNewDev;
  152. PropSheetHeader->pfnCallback = iNDWDlgCallback;
  153. switch (NewDevWiz->InstallType) {
  154. case NDWTYPE_FOUNDNEW:
  155. Title = (LPTSTR)IDS_FOUNDDEVICE;
  156. break;
  157. case NDWTYPE_UPDATE:
  158. Title = (LPTSTR)IDS_UPDATEDEVICE;
  159. break;
  160. default:
  161. Title = TEXT(""); // unknown
  162. }
  163. PropSheetHeader->pszCaption = Title;
  164. PropSheetHeader->phpage = NdwPropertySheet->PropSheetPages;
  165. PropSheetHeader->nStartPage = 0;
  166. PropSheetHeader->nPages = 0;
  167. psp.dwSize = sizeof(PROPSHEETPAGE);
  168. psp.hInstance = hNewDev;
  169. psp.lParam = (LPARAM)NewDevWiz;
  170. psp.pszTitle = Title;
  171. //
  172. // The install wizards are always spawned from some other disjoint UI,
  173. // (HdwWiz, devmgr, cpl applets etc. and so don't have a proper intro
  174. // page.
  175. //
  176. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  177. if (StartPageId == IDD_NEWDEVWIZ_INSTALLDEV) {
  178. //
  179. // Found New Hardware, with a rank Zero match.
  180. // jump straight into install page.
  181. //
  182. ;
  183. }
  184. else {
  185. //
  186. // Update driver, or found new hardware without rank Zero driver
  187. //
  188. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HIDEHEADER;
  189. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_INTRO);
  190. psp.pfnDlgProc = IntroDlgProc;
  191. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  192. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  193. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_ADVANCEDSEARCH);
  194. psp.pszHeaderSubTitle = NULL;
  195. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_ADVANCEDSEARCH);
  196. psp.pfnDlgProc = AdvancedSearchDlgProc;
  197. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  198. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_SEARCHING);
  199. psp.pszHeaderSubTitle = NULL;
  200. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_SEARCHING);
  201. psp.pfnDlgProc = DriverSearchingDlgProc;
  202. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  203. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_WUPROMPT);
  204. psp.pszHeaderSubTitle = NULL;
  205. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_WUPROMPT);
  206. psp.pfnDlgProc = WUPromptDlgProc;
  207. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  208. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_LISTDRIVERS);
  209. psp.pszHeaderSubTitle = NULL;
  210. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_LISTDRIVERS);
  211. psp.pfnDlgProc = ListDriversDlgProc;
  212. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  213. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_SELECTCLASS);
  214. psp.pszHeaderSubTitle = NULL;
  215. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_SELECTCLASS);
  216. psp.pfnDlgProc = NDW_PickClassDlgProc;
  217. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  218. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_SELECTDEVICE);
  219. psp.pszHeaderSubTitle = NULL;
  220. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_SELECTDEVICE);
  221. psp.pfnDlgProc = NDW_SelectDeviceDlgProc;
  222. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  223. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_ANALYZEDEV);
  224. psp.pszHeaderSubTitle = NULL;
  225. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_ANALYZEDEV);
  226. psp.pfnDlgProc = NDW_AnalyzeDlgProc;
  227. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  228. //
  229. // These last two wizard pages are finish pages...so hide the header
  230. //
  231. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HIDEHEADER;
  232. psp.pszHeaderSubTitle = NULL;
  233. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_USECURRENT_FINISH);
  234. psp.pfnDlgProc = UseCurrentDlgProc;
  235. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  236. psp.pszHeaderSubTitle = NULL;
  237. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_NODRIVER_FINISH);
  238. psp.pfnDlgProc = NoDriverDlgProc;
  239. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  240. }
  241. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  242. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_INSTALLDEV);
  243. psp.pszHeaderSubTitle = NULL;
  244. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_INSTALLDEV);
  245. psp.pfnDlgProc = NDW_InstallDevDlgProc;
  246. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  247. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HIDEHEADER;
  248. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_FINISH);
  249. psp.pfnDlgProc = NDW_FinishDlgProc;
  250. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  251. //
  252. // Get the Class Icon Image Lists.
  253. //
  254. NewDevWiz->ClassImageList.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
  255. if (SetupDiGetClassImageList(&NewDevWiz->ClassImageList)) {
  256. HICON hIcon;
  257. //
  258. // Add the blank icon for "Show All Devices"
  259. //
  260. if ((hIcon = LoadIcon(hNewDev, MAKEINTRESOURCE(IDI_BLANK))) != NULL) {
  261. g_BlankIconIndex = ImageList_AddIcon(NewDevWiz->ClassImageList.ImageList, hIcon);
  262. }
  263. } else {
  264. NewDevWiz->ClassImageList.cbSize = 0;
  265. }
  266. NewDevWiz->CurrCursor = NULL;
  267. NewDevWiz->IdcWait = LoadCursor(NULL, IDC_WAIT);
  268. NewDevWiz->IdcAppStarting = LoadCursor(NULL, IDC_APPSTARTING);
  269. NewDevWiz->IdcArrow = LoadCursor(NULL, IDC_ARROW);
  270. return NdwPropertySheet;
  271. }
  272. //
  273. // Used by "Found New Hardware" when a rank zero compatible driver is found
  274. // from the default inf location.
  275. //
  276. BOOL
  277. DoDeviceWizard(
  278. HWND hWnd,
  279. PNEWDEVWIZ NewDevWiz,
  280. BOOL bUpdate
  281. )
  282. {
  283. int PropSheetResult = 0;
  284. PNDWPROPERTYSHEET NdwPropertySheet;
  285. NdwPropertySheet = InitNDWPropSheet(hWnd,
  286. NewDevWiz,
  287. bUpdate ? 0 : IDD_NEWDEVWIZ_INSTALLDEV
  288. );
  289. if (NdwPropertySheet) {
  290. CoInitialize(NULL);
  291. PropSheetResult = (int)PropertySheet(&NdwPropertySheet->PropSheetHeader);
  292. CoUninitialize();
  293. LocalFree(NdwPropertySheet);
  294. }
  295. //
  296. // If there were no other errors encounted while installing drivers and the
  297. // user canceled out of the wizard, then set the LastError to ERROR_CANCELED.
  298. //
  299. if ((NewDevWiz->LastError == ERROR_SUCCESS) &&
  300. (PropSheetResult == 0)) {
  301. NewDevWiz->LastError = ERROR_CANCELLED;
  302. }
  303. //
  304. // Final cleanup of DeviceInfoData and DeviceInfoList.
  305. //
  306. if (NewDevWiz->ClassGuidList) {
  307. LocalFree(NewDevWiz->ClassGuidList);
  308. NewDevWiz->ClassGuidList = NULL;
  309. NewDevWiz->ClassGuidSize = NewDevWiz->ClassGuidNum = 0;
  310. }
  311. //
  312. // Destroy the ClassImageList
  313. //
  314. if (NewDevWiz->ClassImageList.cbSize) {
  315. SetupDiDestroyClassImageList(&NewDevWiz->ClassImageList);
  316. NewDevWiz->ClassImageList.cbSize = 0;
  317. }
  318. return NewDevWiz->LastError == ERROR_SUCCESS;
  319. }
  320. BOOL
  321. InstallSelectedDriver(
  322. HWND hwndParent,
  323. HDEVINFO hDeviceInfo,
  324. LPCWSTR DisplayName,
  325. BOOL Backup,
  326. PDWORD pReboot
  327. )
  328. /*++
  329. Routine Description:
  330. Installs the selected driver on the selected device in the hDeviceInfo.
  331. Arguments:
  332. hwndParent - Window handle of the top-level window to use for any UI related
  333. to installing the device.
  334. HDEVINFO hDeviceInfo - DeviceInfoList which supplies the selected device to install the
  335. selected driver on.
  336. DisplayName - Friendly backup string
  337. Backup - BOOL that indicates whether or not we should back up the current drivers before
  338. installing the new ones.
  339. pReboot - Optional address of variable to receive reboot flags (DI_NEEDRESTART,DI_NEEDREBOOT)
  340. Return Value:
  341. BOOL TRUE if the driver was installed
  342. FALSE if the driver was not installed. Check GetLastError() to see if the specific
  343. error.
  344. --*/
  345. {
  346. NEWDEVWIZ NewDevWiz;
  347. UPDATEDRIVERINFO UpdateDriverInfo;
  348. //
  349. // If someone calls the 32-bit newdev.dll on a 64-bit OS then we need
  350. // to fail and set the last error to ERROR_IN_WOW64.
  351. //
  352. if (GetIsWow64()) {
  353. SetLastError(ERROR_IN_WOW64);
  354. return FALSE;
  355. }
  356. memset(&NewDevWiz, 0, sizeof(NewDevWiz));
  357. NewDevWiz.InstallType = NDWTYPE_UPDATE;
  358. NewDevWiz.hDeviceInfo = hDeviceInfo;
  359. try {
  360. NewDevWiz.DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  361. if (!SetupDiGetSelectedDevice(NewDevWiz.hDeviceInfo,
  362. &NewDevWiz.DeviceInfoData
  363. ))
  364. {
  365. NewDevWiz.LastError = GetLastError();
  366. goto INDLeaveExcept;
  367. }
  368. NewDevWiz.ClassGuidSelected = &NewDevWiz.DeviceInfoData.ClassGuid;
  369. if (!SetupDiGetClassDescription(NewDevWiz.ClassGuidSelected,
  370. NewDevWiz.ClassDescription,
  371. sizeof(NewDevWiz.ClassDescription)/sizeof(TCHAR),
  372. NULL
  373. )
  374. ||
  375. !SetupDiClassNameFromGuid(NewDevWiz.ClassGuidSelected,
  376. NewDevWiz.ClassName,
  377. sizeof(NewDevWiz.ClassName)/sizeof(TCHAR),
  378. NULL
  379. ))
  380. {
  381. NewDevWiz.LastError = GetLastError();
  382. goto INDLeaveExcept;
  383. }
  384. if (Backup) {
  385. UpdateDriverInfo.DisplayName = DisplayName;
  386. UpdateDriverInfo.FromInternet = TRUE;
  387. NewDevWiz.UpdateDriverInfo = &UpdateDriverInfo;
  388. } else {
  389. NewDevWiz.Flags |= IDI_FLAG_NOBACKUP;
  390. }
  391. //
  392. // If the driver we are installing is not digitally signed then we
  393. // want to set a system restore point.
  394. //
  395. NewDevWiz.Flags |= IDI_FLAG_SETRESTOREPOINT;
  396. //
  397. // Do the install quietly since we may have a batch of installs to do,
  398. // only showing UI when really needed.
  399. //
  400. NewDevWiz.SilentMode = TRUE;
  401. DoDeviceWizard(hwndParent, &NewDevWiz, FALSE);
  402. INDLeaveExcept:;
  403. } except(NdwUnhandledExceptionFilter(GetExceptionInformation())) {
  404. NewDevWiz.LastError = RtlNtStatusToDosError(GetExceptionCode());
  405. }
  406. if (pReboot) {
  407. //
  408. // copy out the reboot flags for the caller
  409. //
  410. *pReboot = NewDevWiz.Reboot;
  411. } else if (NewDevWiz.Reboot) {
  412. //
  413. // The caller didn't want the reboot flags so just prompt for a reboot
  414. // ourselves if one is needed.
  415. //
  416. RestartDialogEx(hwndParent, NULL, EWX_REBOOT, REASON_PLANNED_FLAG | REASON_HWINSTALL);
  417. }
  418. SetLastError(NewDevWiz.LastError);
  419. return NewDevWiz.LastError == ERROR_SUCCESS;
  420. }
  421. BOOL
  422. InstallSelectedDevice(
  423. HWND hwndParent,
  424. HDEVINFO hDeviceInfo,
  425. PDWORD pReboot
  426. )
  427. /*++
  428. Routine Description:
  429. Installs the selected device in the hDeviceInfo.
  430. Arguments:
  431. hwndParent - Window handle of the top-level window to use for any UI related
  432. to installing the device.
  433. HDEVINFO hDeviceInfo - DeviceInfoList which supplies the selected device to install.
  434. pReboot - Optional address of variable to receive reboot flags (DI_NEEDRESTART,DI_NEEDREBOOT)
  435. Return Value:
  436. BOOL TRUE for success (does not mean device was installed or updated),
  437. FALSE unexpected error. GetLastError returns the winerror code.
  438. --*/
  439. {
  440. BOOL DriversFound;
  441. NEWDEVWIZ NewDevWiz;
  442. SP_DRVINFO_DATA DriverInfoData;
  443. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  444. //
  445. // If someone calls the 32-bit newdev.dll on a 64-bit OS then we need
  446. // to fail and set the last error to ERROR_IN_WOW64.
  447. //
  448. if (GetIsWow64()) {
  449. SetLastError(ERROR_IN_WOW64);
  450. return FALSE;
  451. }
  452. memset(&NewDevWiz, 0, sizeof(NewDevWiz));
  453. NewDevWiz.InstallType = NDWTYPE_FOUNDNEW;
  454. NewDevWiz.hDeviceInfo = hDeviceInfo;
  455. try {
  456. NewDevWiz.DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  457. if (!SetupDiGetSelectedDevice(NewDevWiz.hDeviceInfo,
  458. &NewDevWiz.DeviceInfoData
  459. ))
  460. {
  461. NewDevWiz.LastError = GetLastError();
  462. goto INDLeaveExcept;
  463. }
  464. NewDevWiz.ClassGuidSelected = &NewDevWiz.DeviceInfoData.ClassGuid;
  465. if (!SetupDiGetClassDescription(NewDevWiz.ClassGuidSelected,
  466. NewDevWiz.ClassDescription,
  467. sizeof(NewDevWiz.ClassDescription)/sizeof(TCHAR),
  468. NULL
  469. )
  470. ||
  471. !SetupDiClassNameFromGuid(NewDevWiz.ClassGuidSelected,
  472. NewDevWiz.ClassName,
  473. sizeof(NewDevWiz.ClassName)/sizeof(TCHAR),
  474. NULL
  475. ))
  476. {
  477. NewDevWiz.LastError = GetLastError();
  478. goto INDLeaveExcept;
  479. }
  480. //
  481. // Do the install quietly since we may have a batch of installs to do,
  482. // only showing UI when really needed. During legacy detect the
  483. // detect summary page is showing.
  484. //
  485. NewDevWiz.SilentMode = TRUE;
  486. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  487. //
  488. // If the driver we are installing is not digitally signed then we
  489. // want to set a system restore point.
  490. //
  491. NewDevWiz.Flags = IDI_FLAG_SETRESTOREPOINT;
  492. if (SetupDiGetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  493. &NewDevWiz.DeviceInfoData,
  494. &DeviceInstallParams
  495. ))
  496. {
  497. DeviceInstallParams.Flags |= DI_SHOWOEM | DI_QUIETINSTALL;
  498. DeviceInstallParams.hwndParent = hwndParent;
  499. wcscpy(DeviceInstallParams.DriverPath, L"");
  500. SetupDiSetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  501. &NewDevWiz.DeviceInfoData,
  502. &DeviceInstallParams
  503. );
  504. }
  505. //
  506. // If no driver list search the win inf default locations
  507. // If we still can't find a driver, then start at the driver
  508. // search page.
  509. //
  510. // otherwise go straight to the finish page and install.
  511. // To preserve drivers preselected by the caller (legacy detect)
  512. // the currently SelectedDriver is used, but if there is no selected
  513. // driver the highest ranking driver is used.
  514. //
  515. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  516. DriversFound = SetupDiEnumDriverInfo(NewDevWiz.hDeviceInfo,
  517. &NewDevWiz.DeviceInfoData,
  518. SPDIT_COMPATDRIVER,
  519. 0,
  520. &DriverInfoData
  521. );
  522. if (!DriversFound) {
  523. SetupDiDestroyDriverInfoList(NewDevWiz.hDeviceInfo,
  524. &NewDevWiz.DeviceInfoData,
  525. SPDIT_COMPATDRIVER
  526. );
  527. if (SetupDiGetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  528. &NewDevWiz.DeviceInfoData,
  529. &DeviceInstallParams
  530. ))
  531. {
  532. wcscpy(DeviceInstallParams.DriverPath, L"");
  533. SetupDiSetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  534. &NewDevWiz.DeviceInfoData,
  535. &DeviceInstallParams
  536. );
  537. }
  538. if (SetupDiBuildDriverInfoList(NewDevWiz.hDeviceInfo,
  539. &NewDevWiz.DeviceInfoData,
  540. SPDIT_COMPATDRIVER
  541. ))
  542. {
  543. SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  544. NewDevWiz.hDeviceInfo,
  545. &NewDevWiz.DeviceInfoData
  546. );
  547. }
  548. DriversFound = SetupDiEnumDriverInfo(NewDevWiz.hDeviceInfo,
  549. &NewDevWiz.DeviceInfoData,
  550. SPDIT_COMPATDRIVER,
  551. 0,
  552. &DriverInfoData
  553. );
  554. }
  555. if (DriversFound) {
  556. SP_DRVINFO_DATA SelectedDriverInfo;
  557. SelectedDriverInfo.cbSize = sizeof(SP_DRVINFO_DATA);
  558. if (!SetupDiGetSelectedDriver(NewDevWiz.hDeviceInfo,
  559. &NewDevWiz.DeviceInfoData,
  560. &SelectedDriverInfo
  561. ))
  562. {
  563. SetupDiSetSelectedDriver(NewDevWiz.hDeviceInfo,
  564. &NewDevWiz.DeviceInfoData,
  565. &DriverInfoData
  566. );
  567. }
  568. DoDeviceWizard(hwndParent, &NewDevWiz, FALSE);
  569. }
  570. else {
  571. DoDeviceWizard(hwndParent, &NewDevWiz, TRUE);
  572. }
  573. if (pReboot) {
  574. //
  575. // copy out the reboot flags for the caller
  576. //
  577. *pReboot = NewDevWiz.Reboot;
  578. } else if (NewDevWiz.Reboot) {
  579. //
  580. // The caller didn't want the reboot flags so just prompt for a reboot
  581. // ourselves if one is needed.
  582. //
  583. RestartDialogEx(hwndParent, NULL, EWX_REBOOT, REASON_PLANNED_FLAG | REASON_HWINSTALL);
  584. }
  585. INDLeaveExcept:;
  586. } except(NdwUnhandledExceptionFilter(GetExceptionInformation())) {
  587. NewDevWiz.LastError = RtlNtStatusToDosError(GetExceptionCode());
  588. }
  589. if (NewDevWiz.hDeviceInfo &&
  590. (NewDevWiz.hDeviceInfo != INVALID_HANDLE_VALUE)) {
  591. SetupDiDestroyDriverInfoList(NewDevWiz.hDeviceInfo, &NewDevWiz.DeviceInfoData, SPDIT_COMPATDRIVER);
  592. SetupDiDestroyDeviceInfoList(NewDevWiz.hDeviceInfo);
  593. }
  594. SetLastError(NewDevWiz.LastError);
  595. return NewDevWiz.LastError == ERROR_SUCCESS;
  596. }
  597. BOOL
  598. InstallNewDevice(
  599. HWND hwndParent,
  600. LPGUID ClassGuid,
  601. PDWORD pReboot
  602. )
  603. /*++
  604. Routine Description:
  605. Exported Entry point from newdev.dll. Installs a new device. A new Devnode is
  606. created and the user is prompted to select the device. If the class guid
  607. is not specified then then the user begins at class selection.
  608. This function has been moved to hdwwiz.cpl (which handles all legacy device
  609. functions now). This entry point just forwards the function call onto hdwwiz.cpl
  610. now.
  611. Arguments:
  612. hwndParent - Window handle of the top-level window to use for any UI related
  613. to installing the device.
  614. LPGUID ClassGuid - Optional class of the new device to install.
  615. If ClassGuid is NULL we start at detection choice page.
  616. If ClassGuid == GUID_NULL or GUID_DEVCLASS_UNKNOWN
  617. we start at class selection page.
  618. pReboot - Optional address of variable to receive reboot flags (DI_NEEDRESTART,DI_NEEDREBOOT)
  619. Return Value:
  620. BOOL TRUE for success (does not mean device was installed or updated),
  621. FALSE unexpected error. GetLastError returns the winerror code.
  622. --*/
  623. {
  624. HMODULE hHdwWiz;
  625. BOOL Return = FALSE;
  626. //
  627. // If someone calls the 32-bit newdev.dll on a 64-bit OS then we need
  628. // to fail and set the last error to ERROR_IN_WOW64.
  629. //
  630. if (GetIsWow64()) {
  631. SetLastError(ERROR_IN_WOW64);
  632. return FALSE;
  633. }
  634. hHdwWiz = LoadLibrary(TEXT("hdwwiz.cpl"));
  635. if (NULL == hHdwWiz) {
  636. return FALSE;
  637. }
  638. if (NULL == pInstallNewDevice) {
  639. pInstallNewDevice = (PINSTALLNEWDEVICE)GetProcAddress(hHdwWiz, "InstallNewDevice");
  640. }
  641. if (NULL == pInstallNewDevice) {
  642. return FALSE;
  643. }
  644. Return = (pInstallNewDevice)(hwndParent, ClassGuid, pReboot);
  645. FreeLibrary(hHdwWiz);
  646. return Return;
  647. }