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.

846 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation
  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. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  172. if (StartPageId == IDD_NEWDEVWIZ_INSTALLDEV) {
  173. //
  174. // Found New Hardware, with a rank Zero match.
  175. // jump straight into install page.
  176. //
  177. ;
  178. }
  179. else {
  180. //
  181. // Update driver, or found new hardware without rank Zero driver
  182. //
  183. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HIDEHEADER;
  184. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_INTRO);
  185. psp.pfnDlgProc = IntroDlgProc;
  186. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  187. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  188. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_ADVANCEDSEARCH);
  189. psp.pszHeaderSubTitle = NULL;
  190. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_ADVANCEDSEARCH);
  191. psp.pfnDlgProc = AdvancedSearchDlgProc;
  192. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  193. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_SEARCHING);
  194. psp.pszHeaderSubTitle = NULL;
  195. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_SEARCHING);
  196. psp.pfnDlgProc = DriverSearchingDlgProc;
  197. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  198. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_WUPROMPT);
  199. psp.pszHeaderSubTitle = NULL;
  200. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_WUPROMPT);
  201. psp.pfnDlgProc = WUPromptDlgProc;
  202. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  203. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_LISTDRIVERS);
  204. psp.pszHeaderSubTitle = NULL;
  205. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_LISTDRIVERS);
  206. psp.pfnDlgProc = ListDriversDlgProc;
  207. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  208. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_SELECTCLASS);
  209. psp.pszHeaderSubTitle = NULL;
  210. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_SELECTCLASS);
  211. psp.pfnDlgProc = NDW_PickClassDlgProc;
  212. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  213. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_SELECTDEVICE);
  214. psp.pszHeaderSubTitle = NULL;
  215. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_SELECTDEVICE);
  216. psp.pfnDlgProc = NDW_SelectDeviceDlgProc;
  217. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  218. //
  219. // These last two wizard pages are finish pages...so hide the header
  220. //
  221. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HIDEHEADER;
  222. psp.pszHeaderSubTitle = NULL;
  223. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_USECURRENT_FINISH);
  224. psp.pfnDlgProc = UseCurrentDlgProc;
  225. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  226. psp.pszHeaderSubTitle = NULL;
  227. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_NODRIVER_FINISH);
  228. psp.pfnDlgProc = NoDriverDlgProc;
  229. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  230. }
  231. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  232. psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NEWDEVWIZ_INSTALLDEV);
  233. psp.pszHeaderSubTitle = NULL;
  234. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_INSTALLDEV);
  235. psp.pfnDlgProc = NDW_InstallDevDlgProc;
  236. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  237. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HIDEHEADER;
  238. psp.pszTemplate = MAKEINTRESOURCE(IDD_NEWDEVWIZ_FINISH);
  239. psp.pfnDlgProc = NDW_FinishDlgProc;
  240. PropSheetHeader->phpage[PropSheetHeader->nPages++] = CreatePropertySheetPage(&psp);
  241. //
  242. // Get the Class Icon Image Lists.
  243. //
  244. NewDevWiz->ClassImageList.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
  245. if (SetupDiGetClassImageList(&NewDevWiz->ClassImageList)) {
  246. HICON hIcon;
  247. //
  248. // Add the blank icon for "Show All Devices"
  249. //
  250. if ((hIcon = LoadIcon(hNewDev, MAKEINTRESOURCE(IDI_BLANK))) != NULL) {
  251. g_BlankIconIndex = ImageList_AddIcon(NewDevWiz->ClassImageList.ImageList, hIcon);
  252. }
  253. } else {
  254. NewDevWiz->ClassImageList.cbSize = 0;
  255. }
  256. NewDevWiz->CurrCursor = NULL;
  257. NewDevWiz->IdcWait = LoadCursor(NULL, IDC_WAIT);
  258. NewDevWiz->IdcAppStarting = LoadCursor(NULL, IDC_APPSTARTING);
  259. NewDevWiz->IdcArrow = LoadCursor(NULL, IDC_ARROW);
  260. return NdwPropertySheet;
  261. }
  262. BOOL
  263. DoDeviceWizard(
  264. HWND hWnd,
  265. PNEWDEVWIZ NewDevWiz,
  266. BOOL bUpdate
  267. )
  268. {
  269. int PropSheetResult = 0;
  270. PNDWPROPERTYSHEET NdwPropertySheet;
  271. NdwPropertySheet = InitNDWPropSheet(hWnd,
  272. NewDevWiz,
  273. bUpdate ? 0 : IDD_NEWDEVWIZ_INSTALLDEV
  274. );
  275. if (NdwPropertySheet) {
  276. CoInitialize(NULL);
  277. PropSheetResult = (int)PropertySheet(&NdwPropertySheet->PropSheetHeader);
  278. CoUninitialize();
  279. LocalFree(NdwPropertySheet);
  280. }
  281. //
  282. // If there were no other errors encounted while installing drivers and the
  283. // user canceled out of the wizard, then set the LastError to ERROR_CANCELED.
  284. //
  285. if ((NewDevWiz->LastError == ERROR_SUCCESS) &&
  286. (PropSheetResult == 0)) {
  287. NewDevWiz->LastError = ERROR_CANCELLED;
  288. }
  289. //
  290. // Final cleanup of DeviceInfoData and DeviceInfoList.
  291. //
  292. if (NewDevWiz->ClassGuidList) {
  293. LocalFree(NewDevWiz->ClassGuidList);
  294. NewDevWiz->ClassGuidList = NULL;
  295. NewDevWiz->ClassGuidSize = NewDevWiz->ClassGuidNum = 0;
  296. }
  297. //
  298. // Destroy the ClassImageList
  299. //
  300. if (NewDevWiz->ClassImageList.cbSize) {
  301. SetupDiDestroyClassImageList(&NewDevWiz->ClassImageList);
  302. NewDevWiz->ClassImageList.cbSize = 0;
  303. }
  304. return NewDevWiz->LastError == ERROR_SUCCESS;
  305. }
  306. BOOL
  307. InstallSelectedDriver(
  308. HWND hwndParent,
  309. HDEVINFO hDeviceInfo,
  310. LPCWSTR Reserved,
  311. BOOL Backup,
  312. PDWORD pReboot
  313. )
  314. /*++
  315. Routine Description:
  316. Installs the selected driver on the selected device in the hDeviceInfo.
  317. Arguments:
  318. hwndParent - Window handle of the top-level window to use for any UI related
  319. to installing the device.
  320. HDEVINFO hDeviceInfo - DeviceInfoList which supplies the selected device to install the
  321. selected driver on.
  322. Reserved - ignored, should be NULL.
  323. Backup - BOOL that indicates whether or not we should back up the current drivers before
  324. installing the new ones.
  325. pReboot - Optional address of variable to receive reboot flags (DI_NEEDRESTART,DI_NEEDREBOOT)
  326. Return Value:
  327. BOOL TRUE if the driver was installed
  328. FALSE if the driver was not installed. Check GetLastError() to see if the specific
  329. error.
  330. --*/
  331. {
  332. NEWDEVWIZ NewDevWiz;
  333. UPDATEDRIVERINFO UpdateDriverInfo;
  334. UNREFERENCED_PARAMETER(Reserved);
  335. //
  336. // If someone calls the 32-bit newdev.dll on a 64-bit OS then we need
  337. // to fail and set the last error to ERROR_IN_WOW64.
  338. //
  339. if (GetIsWow64()) {
  340. SetLastError(ERROR_IN_WOW64);
  341. return FALSE;
  342. }
  343. //
  344. // Verify that the process has sufficient Administrator privileges.
  345. //
  346. if (!pSetupIsUserAdmin()) {
  347. SetLastError(ERROR_ACCESS_DENIED);
  348. return FALSE;
  349. }
  350. memset(&NewDevWiz, 0, sizeof(NewDevWiz));
  351. NewDevWiz.InstallType = NDWTYPE_UPDATE_SILENT;
  352. NewDevWiz.hDeviceInfo = hDeviceInfo;
  353. try {
  354. NewDevWiz.DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  355. if (!SetupDiGetSelectedDevice(NewDevWiz.hDeviceInfo,
  356. &NewDevWiz.DeviceInfoData
  357. ))
  358. {
  359. NewDevWiz.LastError = GetLastError();
  360. goto INDLeaveExcept;
  361. }
  362. NewDevWiz.ClassGuidSelected = &NewDevWiz.DeviceInfoData.ClassGuid;
  363. if (!SetupDiGetClassDescription(NewDevWiz.ClassGuidSelected,
  364. NewDevWiz.ClassDescription,
  365. SIZECHARS(NewDevWiz.ClassDescription),
  366. NULL
  367. )
  368. ||
  369. !SetupDiClassNameFromGuid(NewDevWiz.ClassGuidSelected,
  370. NewDevWiz.ClassName,
  371. SIZECHARS(NewDevWiz.ClassName),
  372. NULL
  373. ))
  374. {
  375. NewDevWiz.LastError = GetLastError();
  376. goto INDLeaveExcept;
  377. }
  378. ZeroMemory(&UpdateDriverInfo, sizeof(UpdateDriverInfo));
  379. NewDevWiz.UpdateDriverInfo = &UpdateDriverInfo;
  380. if (Backup == FALSE) {
  381. NewDevWiz.Flags |= IDI_FLAG_NOBACKUP;
  382. }
  383. //
  384. // If the driver we are installing is not digitally signed then we
  385. // want to set a system restore point.
  386. //
  387. NewDevWiz.Flags |= IDI_FLAG_SETRESTOREPOINT;
  388. //
  389. // Do the install quietly since we may have a batch of installs to do,
  390. // only showing UI when really needed.
  391. //
  392. NewDevWiz.SilentMode = TRUE;
  393. DoDeviceWizard(hwndParent, &NewDevWiz, FALSE);
  394. INDLeaveExcept:;
  395. } except(NdwUnhandledExceptionFilter(GetExceptionInformation())) {
  396. NewDevWiz.LastError = RtlNtStatusToDosError(GetExceptionCode());
  397. }
  398. if (pReboot) {
  399. //
  400. // copy out the reboot flags for the caller
  401. //
  402. *pReboot = NewDevWiz.Reboot;
  403. } else if (NewDevWiz.Reboot) {
  404. //
  405. // The caller didn't want the reboot flags so just prompt for a reboot
  406. // ourselves if one is needed.
  407. //
  408. RestartDialogEx(hwndParent, NULL, EWX_REBOOT, REASON_PLANNED_FLAG | REASON_HWINSTALL);
  409. }
  410. SetLastError(NewDevWiz.LastError);
  411. return NewDevWiz.LastError == ERROR_SUCCESS;
  412. }
  413. BOOL
  414. InstallSelectedDevice(
  415. HWND hwndParent,
  416. HDEVINFO hDeviceInfo,
  417. PDWORD pReboot
  418. )
  419. /*++
  420. Routine Description:
  421. Installs the selected device in the hDeviceInfo.
  422. Arguments:
  423. hwndParent - Window handle of the top-level window to use for any UI related
  424. to installing the device.
  425. HDEVINFO hDeviceInfo - DeviceInfoList which supplies the selected device to install.
  426. pReboot - Optional address of variable to receive reboot flags (DI_NEEDRESTART,DI_NEEDREBOOT)
  427. Return Value:
  428. BOOL TRUE for success (does not mean device was installed or updated),
  429. FALSE unexpected error. GetLastError returns the winerror code.
  430. --*/
  431. {
  432. BOOL DriversFound;
  433. NEWDEVWIZ NewDevWiz;
  434. SP_DRVINFO_DATA DriverInfoData;
  435. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  436. //
  437. // If someone calls the 32-bit newdev.dll on a 64-bit OS then we need
  438. // to fail and set the last error to ERROR_IN_WOW64.
  439. //
  440. if (GetIsWow64()) {
  441. SetLastError(ERROR_IN_WOW64);
  442. return FALSE;
  443. }
  444. //
  445. // Verify that the process has sufficient Administrator privileges.
  446. //
  447. if (!pSetupIsUserAdmin()) {
  448. SetLastError(ERROR_ACCESS_DENIED);
  449. return FALSE;
  450. }
  451. memset(&NewDevWiz, 0, sizeof(NewDevWiz));
  452. NewDevWiz.InstallType = NDWTYPE_FOUNDNEW;
  453. NewDevWiz.hDeviceInfo = hDeviceInfo;
  454. try {
  455. NewDevWiz.DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  456. if (!SetupDiGetSelectedDevice(NewDevWiz.hDeviceInfo,
  457. &NewDevWiz.DeviceInfoData
  458. ))
  459. {
  460. NewDevWiz.LastError = GetLastError();
  461. goto INDLeaveExcept;
  462. }
  463. NewDevWiz.ClassGuidSelected = &NewDevWiz.DeviceInfoData.ClassGuid;
  464. if (!SetupDiGetClassDescription(NewDevWiz.ClassGuidSelected,
  465. NewDevWiz.ClassDescription,
  466. SIZECHARS(NewDevWiz.ClassDescription),
  467. NULL
  468. )
  469. ||
  470. !SetupDiClassNameFromGuid(NewDevWiz.ClassGuidSelected,
  471. NewDevWiz.ClassName,
  472. SIZECHARS(NewDevWiz.ClassName),
  473. NULL
  474. ))
  475. {
  476. NewDevWiz.LastError = GetLastError();
  477. goto INDLeaveExcept;
  478. }
  479. //
  480. // Do the install quietly since we may have a batch of installs to do,
  481. // only showing UI when really needed. During legacy detect the
  482. // detect summary page is showing.
  483. //
  484. NewDevWiz.SilentMode = TRUE;
  485. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  486. //
  487. // If the driver we are installing is not digitally signed then we
  488. // want to set a system restore point.
  489. //
  490. NewDevWiz.Flags = IDI_FLAG_SETRESTOREPOINT;
  491. if (SetupDiGetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  492. &NewDevWiz.DeviceInfoData,
  493. &DeviceInstallParams
  494. ))
  495. {
  496. DeviceInstallParams.Flags |= DI_SHOWOEM | DI_QUIETINSTALL;
  497. DeviceInstallParams.hwndParent = hwndParent;
  498. DeviceInstallParams.DriverPath[0] = TEXT('\0');
  499. SetupDiSetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  500. &NewDevWiz.DeviceInfoData,
  501. &DeviceInstallParams
  502. );
  503. }
  504. //
  505. // If no driver list search the win inf default locations
  506. // If we still can't find a driver, then start at the driver
  507. // search page.
  508. //
  509. // otherwise go straight to the finish page and install.
  510. // To preserve drivers preselected by the caller (legacy detect)
  511. // the currently SelectedDriver is used, but if there is no selected
  512. // driver the highest ranking driver is used.
  513. //
  514. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  515. DriversFound = SetupDiEnumDriverInfo(NewDevWiz.hDeviceInfo,
  516. &NewDevWiz.DeviceInfoData,
  517. SPDIT_COMPATDRIVER,
  518. 0,
  519. &DriverInfoData
  520. );
  521. if (!DriversFound) {
  522. SetupDiDestroyDriverInfoList(NewDevWiz.hDeviceInfo,
  523. &NewDevWiz.DeviceInfoData,
  524. SPDIT_COMPATDRIVER
  525. );
  526. if (SetupDiGetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  527. &NewDevWiz.DeviceInfoData,
  528. &DeviceInstallParams
  529. ))
  530. {
  531. DeviceInstallParams.DriverPath[0] = TEXT('\0');
  532. SetupDiSetDeviceInstallParams(NewDevWiz.hDeviceInfo,
  533. &NewDevWiz.DeviceInfoData,
  534. &DeviceInstallParams
  535. );
  536. }
  537. if (SetupDiBuildDriverInfoList(NewDevWiz.hDeviceInfo,
  538. &NewDevWiz.DeviceInfoData,
  539. SPDIT_COMPATDRIVER
  540. ))
  541. {
  542. SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  543. NewDevWiz.hDeviceInfo,
  544. &NewDevWiz.DeviceInfoData
  545. );
  546. }
  547. DriversFound = SetupDiEnumDriverInfo(NewDevWiz.hDeviceInfo,
  548. &NewDevWiz.DeviceInfoData,
  549. SPDIT_COMPATDRIVER,
  550. 0,
  551. &DriverInfoData
  552. );
  553. }
  554. if (DriversFound) {
  555. SP_DRVINFO_DATA SelectedDriverInfo;
  556. SelectedDriverInfo.cbSize = sizeof(SP_DRVINFO_DATA);
  557. if (!SetupDiGetSelectedDriver(NewDevWiz.hDeviceInfo,
  558. &NewDevWiz.DeviceInfoData,
  559. &SelectedDriverInfo
  560. ))
  561. {
  562. SetupDiSetSelectedDriver(NewDevWiz.hDeviceInfo,
  563. &NewDevWiz.DeviceInfoData,
  564. &DriverInfoData
  565. );
  566. }
  567. DoDeviceWizard(hwndParent, &NewDevWiz, FALSE);
  568. }
  569. else {
  570. DoDeviceWizard(hwndParent, &NewDevWiz, TRUE);
  571. }
  572. if (pReboot) {
  573. //
  574. // copy out the reboot flags for the caller
  575. //
  576. *pReboot = NewDevWiz.Reboot;
  577. } else if (NewDevWiz.Reboot) {
  578. //
  579. // The caller didn't want the reboot flags so just prompt for a reboot
  580. // ourselves if one is needed.
  581. //
  582. RestartDialogEx(hwndParent, NULL, EWX_REBOOT, REASON_PLANNED_FLAG | REASON_HWINSTALL);
  583. }
  584. INDLeaveExcept:;
  585. } except(NdwUnhandledExceptionFilter(GetExceptionInformation())) {
  586. NewDevWiz.LastError = RtlNtStatusToDosError(GetExceptionCode());
  587. }
  588. if (NewDevWiz.hDeviceInfo &&
  589. (NewDevWiz.hDeviceInfo != INVALID_HANDLE_VALUE)) {
  590. SetupDiDestroyDriverInfoList(NewDevWiz.hDeviceInfo, &NewDevWiz.DeviceInfoData, SPDIT_COMPATDRIVER);
  591. SetupDiDestroyDeviceInfoList(NewDevWiz.hDeviceInfo);
  592. }
  593. SetLastError(NewDevWiz.LastError);
  594. return NewDevWiz.LastError == ERROR_SUCCESS;
  595. }
  596. BOOL
  597. InstallNewDevice(
  598. HWND hwndParent,
  599. LPGUID ClassGuid,
  600. PDWORD pReboot
  601. )
  602. /*++
  603. Routine Description:
  604. Exported Entry point from newdev.dll. Installs a new device. A new Devnode is
  605. created and the user is prompted to select the device. If the class guid
  606. is not specified then then the user begins at class selection.
  607. This function has been moved to hdwwiz.cpl (which handles all legacy device
  608. functions now). This entry point just forwards the function call onto hdwwiz.cpl
  609. now.
  610. Arguments:
  611. hwndParent - Window handle of the top-level window to use for any UI related
  612. to installing the device.
  613. LPGUID ClassGuid - Optional class of the new device to install.
  614. If ClassGuid is NULL we start at detection choice page.
  615. If ClassGuid == GUID_NULL or GUID_DEVCLASS_UNKNOWN
  616. we start at class selection page.
  617. pReboot - Optional address of variable to receive reboot flags (DI_NEEDRESTART,DI_NEEDREBOOT)
  618. Return Value:
  619. BOOL TRUE for success (does not mean device was installed or updated),
  620. FALSE unexpected error. GetLastError returns the winerror code.
  621. --*/
  622. {
  623. HMODULE hHdwWiz = NULL;
  624. BOOL Return = FALSE;
  625. //
  626. // If someone calls the 32-bit newdev.dll on a 64-bit OS then we need
  627. // to fail and set the last error to ERROR_IN_WOW64.
  628. //
  629. if (GetIsWow64()) {
  630. SetLastError(ERROR_IN_WOW64);
  631. return FALSE;
  632. }
  633. hHdwWiz = LoadLibrary(TEXT("HDWWIZ.CPL"));
  634. if (NULL == hHdwWiz) {
  635. return FALSE;
  636. }
  637. if (NULL == pInstallNewDevice) {
  638. pInstallNewDevice = (PINSTALLNEWDEVICE)GetProcAddress(hHdwWiz, "InstallNewDevice");
  639. }
  640. if (NULL == pInstallNewDevice) {
  641. return FALSE;
  642. }
  643. Return = (pInstallNewDevice)(hwndParent, ClassGuid, pReboot);
  644. FreeLibrary(hHdwWiz);
  645. return Return;
  646. }