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.

1292 lines
42 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation
  3. Module Name:
  4. devdrvpg.cpp
  5. Abstract:
  6. This module implements CDeviceDriverPage -- device driver property page
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. // devdrvpg.cpp : implementation file
  12. //
  13. #include "devmgr.h"
  14. #include "devdrvpg.h"
  15. #include "cdriver.h"
  16. #include "tswizard.h"
  17. #include "devrmdlg.h"
  18. //
  19. // help topic ids
  20. //
  21. const DWORD g_a106HelpIDs[]=
  22. {
  23. IDC_DEVDRV_ICON, IDH_DISABLEHELP, // Driver: "" (Static)
  24. IDC_DEVDRV_DESC, IDH_DISABLEHELP, // Driver: "" (Static)
  25. IDC_DEVDRV_TITLE_DRIVERPROVIDER, idh_devmgr_driver_provider_main,
  26. IDC_DEVDRV_DRIVERPROVIDER, idh_devmgr_driver_provider_main,
  27. IDC_DEVDRV_TITLE_DRIVERDATE, idh_devmgr_driver_date_main,
  28. IDC_DEVDRV_DRIVERDATE, idh_devmgr_driver_date_main,
  29. IDC_DEVDRV_TITLE_DRIVERVERSION, idh_devmgr_driver_version_main,
  30. IDC_DEVDRV_DRIVERVERSION, idh_devmgr_driver_version_main,
  31. IDC_DEVDRV_TITLE_DRIVERSIGNER, idh_devmgr_digital_signer,
  32. IDC_DEVDRV_DRIVERSIGNER, idh_devmgr_digital_signer,
  33. IDC_DEVDRV_DETAILS, idh_devmgr_devdrv_details, // Driver: "Driver Details" (Button)
  34. IDC_DEVDRV_DETAILS_TEXT, idh_devmgr_devdrv_details, // Driver: "Driver Details" (Button)
  35. IDC_DEVDRV_UNINSTALL, idh_devmgr_devdrv_uninstall, // Driver: "Uninstall" (Button)
  36. IDC_DEVDRV_UNINSTALL_TEXT, idh_devmgr_devdrv_uninstall, // Driver: "Uninstall" (Button)
  37. IDC_DEVDRV_CHANGEDRIVER, idh_devmgr_driver_change_driver, // Driver: "&Change Driver..." (Button)
  38. IDC_DEVDRV_CHANGEDRIVER_TEXT, idh_devmgr_driver_change_driver, // Driver: "&Change Driver..." (Button)
  39. IDC_DEVDRV_ROLLBACK, idh_devmgr_rollback_button, // Driver: "Roll Back Driver..." (Button)
  40. IDC_DEVDRV_ROLLBACK_TEXT, idh_devmgr_rollback_button, // Driver: "Roll Back Driver..." (Button)
  41. 0, 0
  42. };
  43. CDeviceDriverPage::~CDeviceDriverPage()
  44. {
  45. if (m_pDriver) {
  46. delete m_pDriver;
  47. }
  48. }
  49. BOOL
  50. CDeviceDriverPage::OnCommand(
  51. WPARAM wParam,
  52. LPARAM lParam
  53. )
  54. {
  55. UNREFERENCED_PARAMETER(lParam);
  56. if (BN_CLICKED == HIWORD(wParam)) {
  57. switch (LOWORD(wParam)) {
  58. case IDC_DEVDRV_DETAILS:
  59. {
  60. //
  61. // We first need to call CDriver::BuildDriverList to build up a list
  62. // of drivers for this device. This can take some time so we will put
  63. // up the busy cursor.
  64. //
  65. HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  66. CDriver* pDriver;
  67. pDriver = m_pDevice->CreateDriver();
  68. if (pDriver) {
  69. pDriver->BuildDriverList();
  70. SetCursor(hCursorOld);
  71. //
  72. // Show driver file details
  73. //
  74. if (pDriver->GetCount() > 0) {
  75. if (pDriver) {
  76. CDriverFilesDlg DriverFilesDlg(m_pDevice, pDriver);
  77. DriverFilesDlg.DoModal(m_hDlg, (LPARAM)&DriverFilesDlg);
  78. }
  79. } else {
  80. //
  81. // No driver files are loaded for this device
  82. //
  83. String strNoDrivers;
  84. strNoDrivers.LoadString(g_hInstance, IDS_DEVDRV_NODRIVERFILE);
  85. MessageBox(m_hDlg, strNoDrivers, m_pDevice->GetDisplayName(), MB_OK);
  86. return FALSE;
  87. }
  88. delete pDriver;
  89. pDriver = NULL;
  90. }
  91. break;
  92. }
  93. case IDC_DEVDRV_UNINSTALL:
  94. {
  95. BOOL Refresh = (m_pDevice->IsPhantom() ||
  96. m_pDevice->HasProblem() ||
  97. !m_pDevice->IsStarted());
  98. if (UninstallDrivers(m_pDevice, m_hDlg)) {
  99. //
  100. // Enable refresh since we disabled it in the beginning.
  101. //
  102. // We only need to force a refresh here if the device that
  103. // was removed was a Phantom device. This is because Phantom
  104. // devices don't have kernel mode devnodes and so they won't
  105. // generate a WM_DEVICECHANGE like live devnodes will.
  106. //
  107. if (Refresh) {
  108. m_pDevice->m_pMachine->ScheduleRefresh();
  109. }
  110. ::DestroyWindow(GetParent(m_hDlg));
  111. }
  112. break;
  113. }
  114. case IDC_DEVDRV_CHANGEDRIVER:
  115. {
  116. BOOL fChanged;
  117. DWORD Reboot = 0;
  118. if (UpdateDriver(m_pDevice, m_hDlg, &fChanged, &Reboot) && fChanged) {
  119. //
  120. // ISSUE: JasonC 2/7/00
  121. //
  122. // A refresh on m_pDevice->m_pMachine is necessary here.
  123. // Since we are running on a different thread and each
  124. // property page may have cached the HDEVINFO and the
  125. // SP_DEVINFO_DATA, refresh on the CMachine object can not
  126. // be done here. The problem is worsen by the fact that
  127. // user can go back to the device tree and work on the tree
  128. // while this property sheet is still up.
  129. // It would be nice if MMC would support modal dialog boxes!
  130. //
  131. m_pDevice->PropertyChanged();
  132. m_pDevice->GetClass()->PropertyChanged();
  133. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
  134. UpdateControls();
  135. PropSheet_SetTitle(GetParent(m_hDlg), PSH_PROPTITLE, m_pDevice->GetDisplayName());
  136. PropSheet_CancelToClose(GetParent(m_hDlg));
  137. if (Reboot & (DI_NEEDRESTART | DI_NEEDREBOOT)) {
  138. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_NEEDREBOOT);
  139. }
  140. }
  141. break;
  142. }
  143. case IDC_DEVDRV_ROLLBACK:
  144. {
  145. BOOL fChanged;
  146. DWORD Reboot = 0;
  147. if (RollbackDriver(m_pDevice, m_hDlg, &fChanged, &Reboot) && fChanged) {
  148. //
  149. // ISSUE: JasonC 2/7/00
  150. //
  151. // A refresh on m_pDevice->m_pMachine is necessary here.
  152. // Since we are running on a different thread and each
  153. // property page may have cached the HDEVINFO and the
  154. // SP_DEVINFO_DATA, refresh on the CMachine object can not
  155. // be done here. The problem is worsen by the fact that
  156. // user can go back to the device tree and work on the tree
  157. // while this property sheet is still up.
  158. // It would be nice if MMC would support modal dialog boxes!
  159. //
  160. m_pDevice->PropertyChanged();
  161. m_pDevice->GetClass()->PropertyChanged();
  162. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
  163. UpdateControls();
  164. PropSheet_SetTitle(GetParent(m_hDlg), PSH_PROPTITLE, m_pDevice->GetDisplayName());
  165. PropSheet_CancelToClose(GetParent(m_hDlg));
  166. if (Reboot & (DI_NEEDRESTART | DI_NEEDREBOOT)) {
  167. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_NEEDREBOOT);
  168. }
  169. }
  170. break;
  171. }
  172. default:
  173. break;
  174. }
  175. }
  176. return FALSE;
  177. }
  178. //
  179. // This function uninstalls the drivers for the given device
  180. // INPUT:
  181. // pDevice -- the object represent the device
  182. // hDlg -- the property page window handle
  183. //
  184. // OUTPUT:
  185. // TRUE -- function succeeded.
  186. // FALSE -- function failed.
  187. //
  188. BOOL
  189. CDeviceDriverPage::UninstallDrivers(
  190. CDevice* pDevice,
  191. HWND hDlg
  192. )
  193. {
  194. BOOL Return = FALSE;
  195. CMachine *pMachine;
  196. if (pDevice->m_pMachine->m_ParentMachine) {
  197. pMachine = pDevice->m_pMachine->m_ParentMachine;
  198. } else {
  199. pMachine = pDevice->m_pMachine;
  200. }
  201. if(!pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
  202. //
  203. // Must be an admin and on the local machine to remove a device.
  204. //
  205. return FALSE;
  206. }
  207. BOOL Refresh = (pDevice->IsPhantom() ||
  208. pDevice->HasProblem() ||
  209. !pDevice->IsStarted());
  210. pMachine->EnableRefresh(FALSE);
  211. CRemoveDevDlg TheDlg(pDevice);
  212. if (IDOK == TheDlg.DoModal(hDlg, (LPARAM) &TheDlg)) {
  213. DWORD DiFlags;
  214. DiFlags = pDevice->m_pMachine->DiGetFlags(*pDevice);
  215. //
  216. // First try and send a MMCPropertyChangeNotify message to our
  217. // CComponent so that it can prompt for a reboot inside the
  218. // device manager thread instead of our thread. If this is not
  219. // done then the property sheet will hang around after device
  220. // manager has gone away...which will cause a "hung app" dialog
  221. // to appear.
  222. //
  223. // Note: In this case we pass NULL as the Window handle since
  224. // uninstalling will cause the property sheet to go away.
  225. //
  226. CNotifyRebootRequest* pNRR = new CNotifyRebootRequest(NULL, DiFlags, IDS_REMOVEDEV_RESTART);
  227. if (pNRR) {
  228. if (!m_pDevice->m_psd.PropertyChangeNotify(reinterpret_cast<LONG_PTR>(pNRR))) {
  229. //
  230. // There isn't a CComponent around, so this is just a property
  231. // sheet running outside of MMC.
  232. //
  233. pNRR->Release();
  234. PromptForRestart(hDlg, DiFlags, IDS_REMOVEDEV_RESTART);
  235. }
  236. } else {
  237. //
  238. // We couldn't allocate memory to create our CNotifyRebootRequest
  239. // instance, so just prompt for a reboot in this thread.
  240. //
  241. PromptForRestart(hDlg, DiFlags, IDS_REMOVEDEV_RESTART);
  242. }
  243. if (Refresh) {
  244. pMachine->ScheduleRefresh();
  245. }
  246. Return = TRUE;
  247. }
  248. pMachine->EnableRefresh(TRUE);
  249. return Return;
  250. }
  251. BOOL
  252. CDeviceDriverPage::LaunchTroubleShooter(
  253. CDevice* pDevice,
  254. HWND hDlg,
  255. BOOL *pfChanged
  256. )
  257. {
  258. BOOL fChanged = FALSE;
  259. DWORD Status, Problem = 0;
  260. CProblemAgent* ProblemAgent;
  261. if (pDevice->GetStatus(&Status, &Problem) || pDevice->IsPhantom())
  262. {
  263. //
  264. // if the device is a phantom device, use the CM_PROB_DEVICE_NOT_THERE
  265. //
  266. if (pDevice->IsPhantom())
  267. {
  268. Problem = CM_PROB_DEVICE_NOT_THERE;
  269. Status = DN_HAS_PROBLEM;
  270. }
  271. //
  272. // if the device is not started and no problem is assigned to it
  273. // fake the problem number to be failed start.
  274. //
  275. if (!(Status & DN_STARTED) && !Problem && pDevice->IsRAW())
  276. {
  277. Problem = CM_PROB_FAILED_START;
  278. }
  279. }
  280. ProblemAgent = new CProblemAgent(pDevice, Problem, FALSE);
  281. if (ProblemAgent) {
  282. fChanged = ProblemAgent->FixIt(GetParent(hDlg));
  283. delete ProblemAgent;
  284. }
  285. if (pfChanged) {
  286. *pfChanged = fChanged;
  287. }
  288. return TRUE;
  289. }
  290. //
  291. // This function updates drivers for the given device
  292. // INPUT:
  293. // pDevice -- the object represent the device
  294. // hDlg -- the property page window handle
  295. // pfChanged -- optional buffer to receive if driver changes
  296. // have occured.
  297. // OUTPUT:
  298. // TRUE -- function succeeded.
  299. // FALSE -- function failed.
  300. //
  301. BOOL
  302. CDeviceDriverPage::RollbackDriver(
  303. CDevice* pDevice,
  304. HWND hDlg,
  305. BOOL *pfChanged,
  306. DWORD *pdwReboot
  307. )
  308. {
  309. HCURSOR hCursorOld;
  310. BOOL RollbackSuccessful = FALSE;
  311. DWORD RollbackError = ERROR_CANCELLED;
  312. DWORD Status = 0, Problem = 0;
  313. //
  314. // Verify that the process has Admin credentials and that we are running on the local
  315. // machine.
  316. //
  317. if (!pDevice || !pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
  318. ASSERT(FALSE);
  319. return FALSE;
  320. }
  321. hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  322. //
  323. // If the device has the DN_WILL_BE_REMOVED flag set and the user is
  324. // attempting to roll back the driver then we will prompt them for a
  325. // reboot and include text in the prompt that explains this device
  326. // is in the process of being removed.
  327. //
  328. if (pDevice->GetStatus(&Status, &Problem) &&
  329. (Status & DN_WILL_BE_REMOVED)) {
  330. //
  331. // First try and send a MMCPropertyChangeNotify message to our
  332. // CComponent so that it can prompt for a reboot inside the
  333. // device manager thread instead of our thread. If this is not
  334. // done then the property sheet will hang around after device
  335. // manager has gone away...which will cause a "hung app" dialog
  336. // to appear.
  337. //
  338. CNotifyRebootRequest* pNRR = new CNotifyRebootRequest(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_ROLLBACK_DRIVER);
  339. if (pNRR) {
  340. if (!m_pDevice->m_psd.PropertyChangeNotify(reinterpret_cast<LONG_PTR>(pNRR))) {
  341. //
  342. // There isn't a CComponent around, so this is just a property
  343. // sheet running outside of MMC.
  344. //
  345. pNRR->Release();
  346. PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_ROLLBACK_DRIVER);
  347. }
  348. } else {
  349. //
  350. // We couldn't allocate memory to create our CNotifyRebootRequest
  351. // instance, so just prompt for a reboot in this thread.
  352. //
  353. PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_ROLLBACK_DRIVER);
  354. }
  355. return FALSE;
  356. }
  357. //
  358. // First check to see if there are any drivers to Rollback
  359. //
  360. CSafeRegistry regRollback;
  361. TCHAR RollbackSubkeyName[MAX_PATH + 1];
  362. TCHAR ReinstallString[MAX_PATH];
  363. BOOL bFoundMatch = FALSE;
  364. int index = 0;
  365. ReinstallString[0] = TEXT('\0');
  366. RollbackSubkeyName[0] = TEXT('\0');
  367. if (regRollback.Open(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Reinstall"))) {
  368. DWORD SubkeySize = ARRAYLEN(RollbackSubkeyName);
  369. while (!bFoundMatch && regRollback.EnumerateSubkey(index, RollbackSubkeyName, &SubkeySize)) {
  370. CSafeRegistry regRollbackSubkey;
  371. if (regRollbackSubkey.Open(regRollback, RollbackSubkeyName)) {
  372. DWORD regType, cbSize;
  373. LPTSTR DeviceInstanceIds;
  374. cbSize = 0;
  375. if (regRollbackSubkey.GetValue(TEXT("DeviceInstanceIds"), &regType, NULL, &cbSize)) {
  376. //
  377. // Allocate memory to hold the DeviceInstanceIds
  378. //
  379. DeviceInstanceIds = (LPTSTR)LocalAlloc(LPTR, cbSize);
  380. if (DeviceInstanceIds) {
  381. ZeroMemory(DeviceInstanceIds, cbSize);
  382. if (regRollbackSubkey.GetValue(TEXT("DeviceInstanceIds"), &regType,
  383. (PBYTE)DeviceInstanceIds, &cbSize)) {
  384. //
  385. // Compare the list of DeviceInstanceIds in this registry key with this
  386. // devices DeviceInstanceId
  387. //
  388. for (LPTSTR p = DeviceInstanceIds; *p; p += (lstrlen(p) + 1)) {
  389. if (pDevice->GetDeviceID() && !lstrcmpi(p, pDevice->GetDeviceID())) {
  390. bFoundMatch = TRUE;
  391. cbSize = sizeof(ReinstallString);
  392. regRollbackSubkey.GetValue(TEXT("ReinstallString"), &regType,
  393. (PBYTE)ReinstallString, &cbSize);
  394. break;
  395. }
  396. }
  397. }
  398. LocalFree(DeviceInstanceIds);
  399. }
  400. }
  401. }
  402. SubkeySize = ARRAYLEN(RollbackSubkeyName);
  403. index++;
  404. }
  405. }
  406. if (bFoundMatch) {
  407. //
  408. // Check the ReinstallString path to verify that a backup directory actually exists.
  409. // We first need to strip the INF name off of the end of the path.
  410. //
  411. PTSTR p;
  412. //
  413. // Assume that the directory does NOT exist
  414. //
  415. bFoundMatch = FALSE;
  416. if (ReinstallString[0] != TEXT('\0')) {
  417. p = StrRChr(ReinstallString, NULL, TEXT('\\'));
  418. if (p) {
  419. *p = 0;
  420. WIN32_FIND_DATA findData;
  421. HANDLE FindHandle;
  422. UINT OldMode;
  423. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  424. FindHandle = FindFirstFile(ReinstallString, &findData);
  425. if(FindHandle != INVALID_HANDLE_VALUE) {
  426. FindClose(FindHandle);
  427. bFoundMatch = TRUE;
  428. } else {
  429. //
  430. // The directory does not exist. Make sure we clean out the registry key
  431. //
  432. regRollback.DeleteSubkey(RollbackSubkeyName);
  433. }
  434. SetErrorMode(OldMode);
  435. }
  436. }
  437. }
  438. if (bFoundMatch) {
  439. //
  440. // We found a match, lets ask the user if they want to rollback the drivers
  441. //
  442. String strYesRollback;
  443. strYesRollback.LoadString(g_hInstance, IDS_DEVDRV_YESROLLBACK);
  444. if (MessageBox(hDlg, strYesRollback, pDevice->GetDisplayName(), MB_YESNO) == IDYES) {
  445. RollbackSuccessful = pDevice->m_pMachine->RollbackDriver(hDlg, RollbackSubkeyName, 0x3, pdwReboot);
  446. if (!RollbackSuccessful) {
  447. RollbackError = GetLastError();
  448. }
  449. }
  450. } else {
  451. //
  452. // We could not find a drivers backup for this device. Lets ask the user if they want
  453. // to start the troubleshooter.
  454. //
  455. String strNoRollback;
  456. strNoRollback.LoadString(g_hInstance, IDS_DEVDRV_NOROLLBACK);
  457. if (MessageBox(hDlg, strNoRollback, pDevice->GetDisplayName(), MB_YESNO) == IDYES) {
  458. LaunchTroubleShooter(pDevice, hDlg, pfChanged);
  459. }
  460. }
  461. if (hCursorOld) {
  462. SetCursor(hCursorOld);
  463. }
  464. //
  465. // We will assume that something changed when we called InstallDevInst()
  466. // unless it returned FALSE and GetLastError() == ERROR_CANCELLED
  467. //
  468. if (pfChanged) {
  469. *pfChanged = TRUE;
  470. if (!bFoundMatch || (!RollbackSuccessful && (ERROR_CANCELLED == RollbackError))) {
  471. *pfChanged = FALSE;
  472. }
  473. }
  474. return TRUE;
  475. }
  476. //
  477. // This function updates drivers for the given device
  478. // INPUT:
  479. // pDevice -- the object represent the device
  480. // hDlg -- the property page window handle
  481. // pfChanged -- optional buffer to receive if driver changes
  482. // have occured.
  483. // OUTPUT:
  484. // TRUE -- function succeeded.
  485. // FALSE -- function failed.
  486. //
  487. BOOL
  488. CDeviceDriverPage::UpdateDriver(
  489. CDevice* pDevice,
  490. HWND hDlg,
  491. BOOL *pfChanged,
  492. DWORD *pdwReboot
  493. )
  494. {
  495. BOOL Installed = FALSE;
  496. DWORD InstallError = ERROR_SUCCESS;
  497. DWORD Status = 0, Problem = 0;
  498. //
  499. // Must be an admin and on the local machine to update a device.
  500. //
  501. if (!pDevice || !pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
  502. ASSERT(FALSE);
  503. return FALSE;
  504. }
  505. //
  506. // If the device has the DN_WILL_BE_REMOVED flag set and the user is
  507. // attempting to update the driver then we will prompt them for a
  508. // reboot and include text in the prompt that explains this device
  509. // is in the process of being removed.
  510. //
  511. if (pDevice->GetStatus(&Status, &Problem) &&
  512. (Status & DN_WILL_BE_REMOVED)) {
  513. //
  514. // First try and send a MMCPropertyChangeNotify message to our
  515. // CComponent so that it can prompt for a reboot inside the
  516. // device manager thread instead of our thread. If this is not
  517. // done then the property sheet will hang around after device
  518. // manager has gone away...which will cause a "hung app" dialog
  519. // to appear.
  520. //
  521. CNotifyRebootRequest* pNRR = new CNotifyRebootRequest(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
  522. if (pNRR) {
  523. if (!m_pDevice->m_psd.PropertyChangeNotify(reinterpret_cast<LONG_PTR>(pNRR))) {
  524. //
  525. // There isn't a CComponent around, so this is just a property
  526. // sheet running outside of MMC.
  527. //
  528. pNRR->Release();
  529. PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
  530. }
  531. } else {
  532. //
  533. // We couldn't allocate memory to create our CNotifyRebootRequest
  534. // instance, so just prompt for a reboot in this thread.
  535. //
  536. PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
  537. }
  538. return FALSE;
  539. }
  540. Installed = pDevice->m_pMachine->InstallDevInst(hDlg, pDevice->GetDeviceID(), TRUE, pdwReboot);
  541. if (!Installed) {
  542. InstallError = GetLastError();
  543. }
  544. //
  545. // We will assume that something changed when we called InstallDevInst()
  546. // unless it returned FALSE and GetLastError() == ERROR_CANCELLED
  547. //
  548. if (pfChanged) {
  549. *pfChanged = TRUE;
  550. if (!Installed && (ERROR_CANCELLED == InstallError)) {
  551. *pfChanged = FALSE;
  552. }
  553. }
  554. return TRUE;
  555. }
  556. void
  557. CDeviceDriverPage::InitializeDriver()
  558. {
  559. if (m_pDriver) {
  560. delete m_pDriver;
  561. m_pDriver = NULL;
  562. }
  563. m_pDriver = m_pDevice->CreateDriver();
  564. }
  565. void
  566. CDeviceDriverPage::UpdateControls(
  567. LPARAM lParam
  568. )
  569. {
  570. if (lParam) {
  571. m_pDevice = (CDevice*) lParam;
  572. }
  573. try {
  574. //
  575. // Calling PropertyChanged() will update the display name for the device. We need
  576. // to do this in case a 3rd party property sheet did something that could change
  577. // the device's display name.
  578. //
  579. m_pDevice->PropertyChanged();
  580. //
  581. // If we are not running locally then don't bother showing the driver
  582. // details since we can't get a list of the drivers and we can't get
  583. // any information about the driver.
  584. //
  585. if (!m_pDevice->m_pMachine->IsLocal()) {
  586. ::EnableWindow(GetControl(IDC_DEVDRV_DETAILS), FALSE);
  587. ::EnableWindow(GetControl(IDC_DEVDRV_DETAILS_TEXT), FALSE);
  588. }
  589. //
  590. // can not change driver on remote machine or the user
  591. // has no Administrator privilege.
  592. //
  593. if (!m_pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
  594. ::EnableWindow(GetControl(IDC_DEVDRV_CHANGEDRIVER), FALSE);
  595. ::EnableWindow(GetControl(IDC_DEVDRV_CHANGEDRIVER_TEXT), FALSE);
  596. ::EnableWindow(GetControl(IDC_DEVDRV_ROLLBACK), FALSE);
  597. ::EnableWindow(GetControl(IDC_DEVDRV_ROLLBACK_TEXT), FALSE);
  598. ::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL), FALSE);
  599. ::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL_TEXT), FALSE);
  600. }
  601. //
  602. // Hide the uninstall button if the device cannot be uninstalled
  603. //
  604. else if (!m_pDevice->IsUninstallable()) {
  605. ::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL), FALSE);
  606. ::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL_TEXT), FALSE);
  607. }
  608. HICON hIconOld;
  609. m_IDCicon = IDC_DEVDRV_ICON; // Save for cleanup in OnDestroy.
  610. hIconOld = (HICON)SendDlgItemMessage(m_hDlg, IDC_DEVDRV_ICON, STM_SETICON,
  611. (WPARAM)(m_pDevice->LoadClassIcon()),
  612. 0
  613. );
  614. if (hIconOld) {
  615. DestroyIcon(hIconOld);
  616. }
  617. InitializeDriver();
  618. SetDlgItemText(m_hDlg, IDC_DEVDRV_DESC, m_pDevice->GetDisplayName());
  619. String strDriverProvider, strDriverDate, strDriverVersion, strDriverSigner;
  620. m_pDevice->GetProviderString(strDriverProvider);
  621. SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERPROVIDER, strDriverProvider);
  622. m_pDevice->GetDriverDateString(strDriverDate);
  623. SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERDATE, strDriverDate);
  624. m_pDevice->GetDriverVersionString(strDriverVersion);
  625. SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERVERSION, strDriverVersion);
  626. if (m_pDriver) {
  627. m_pDriver->GetDriverSignerString(strDriverSigner);
  628. }
  629. //
  630. // If we could not get a digital signature string or then just display
  631. // Unknown for the Digital Signer.
  632. //
  633. if (strDriverSigner.IsEmpty()) {
  634. strDriverSigner.LoadString(g_hInstance, IDS_UNKNOWN);
  635. }
  636. SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERSIGNER, strDriverSigner);
  637. AddToolTips(m_hDlg, IDC_DEVDRV_DRIVERSIGNER, (LPTSTR)strDriverSigner, &m_hwndDigitalSignerTip);
  638. }
  639. catch (CMemoryException* e) {
  640. e->Delete();
  641. // report memory error
  642. MsgBoxParam(m_hDlg, 0, 0, 0);
  643. }
  644. }
  645. BOOL
  646. CDeviceDriverPage::OnHelp(
  647. LPHELPINFO pHelpInfo
  648. )
  649. {
  650. WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
  651. (ULONG_PTR)g_a106HelpIDs);
  652. return FALSE;
  653. }
  654. BOOL
  655. CDeviceDriverPage::OnContextMenu(
  656. HWND hWnd,
  657. WORD xPos,
  658. WORD yPos
  659. )
  660. {
  661. UNREFERENCED_PARAMETER(xPos);
  662. UNREFERENCED_PARAMETER(yPos);
  663. WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
  664. (ULONG_PTR)g_a106HelpIDs);
  665. return FALSE;
  666. }
  667. //////////////////////////////////////////////////////////////////////////////////////////
  668. //
  669. // Driver Files
  670. //
  671. const DWORD g_a110HelpIDs[]=
  672. {
  673. IDC_DRIVERFILES_ICON, IDH_DISABLEHELP, // Driver: "" (Icon)
  674. IDC_DRIVERFILES_DESC, IDH_DISABLEHELP, // Driver: "" (Static)
  675. IDC_DRIVERFILES_FILES, IDH_DISABLEHELP, // Driver: "Provider:" (Static)
  676. IDC_DRIVERFILES_FILELIST, idh_devmgr_driver_driver_files, // Driver: "" (ListBox)
  677. IDC_DRIVERFILES_TITLE_PROVIDER, idh_devmgr_driver_provider, // Driver: "Provider:" (Static)
  678. IDC_DRIVERFILES_PROVIDER, idh_devmgr_driver_provider, // Driver: "" (Static)
  679. IDC_DRIVERFILES_TITLE_COPYRIGHT,idh_devmgr_driver_copyright, // Driver: "Copyright:" (Static)
  680. IDC_DRIVERFILES_COPYRIGHT, idh_devmgr_driver_copyright, // Driver: "" (Static)
  681. IDC_DRIVERFILES_TITLE_DIGITALSIGNER, IDH_DISABLEHELP,
  682. IDC_DRIVERFILES_DIGITALSIGNER, IDH_DISABLEHELP,
  683. IDC_DRIVERFILES_TITLE_VERSION, idh_devmgr_driver_file_version, // Driver: "Version:" (Static)
  684. IDC_DRIVERFILES_VERSION, idh_devmgr_driver_file_version, // Driver: "File Version:" (Static)
  685. 0, 0
  686. };
  687. BOOL CDriverFilesDlg::OnInitDialog()
  688. {
  689. int SignedIndex = 0, BlankIndex = 0, DriverBlockIndex = 0, CertIndex = 0;
  690. try {
  691. HICON hIcon;
  692. hIcon = (HICON)SendDlgItemMessage(m_hDlg, IDC_DRIVERFILES_ICON, STM_SETICON,
  693. (WPARAM)(m_pDevice->LoadClassIcon()), 0);
  694. if (hIcon) {
  695. DestroyIcon(hIcon);
  696. }
  697. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DESC, m_pDevice->GetDisplayName());
  698. //
  699. // Create the ImageList that contains the signed and blank images.
  700. //
  701. // NOTE: On BiDi builds we need to set the ILC_MIRROR flag so that the
  702. // signed/unsigned icons are not mirrored.
  703. //
  704. m_ImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
  705. GetSystemMetrics(SM_CYSMICON),
  706. ILC_MASK |
  707. ((GetWindowLong(GetParent(m_hDlg), GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
  708. ? ILC_MIRROR
  709. : 0),
  710. 1,
  711. 1
  712. );
  713. if (m_ImageList) {
  714. ImageList_SetBkColor(m_ImageList, GetSysColor(COLOR_WINDOW));
  715. if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BLANK))) != NULL) {
  716. BlankIndex = ImageList_AddIcon(m_ImageList, hIcon);
  717. DestroyIcon(hIcon);
  718. }
  719. if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SIGNED))) != NULL) {
  720. SignedIndex = ImageList_AddIcon(m_ImageList, hIcon);
  721. DestroyIcon(hIcon);
  722. }
  723. if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_CERT))) != NULL) {
  724. CertIndex = ImageList_AddIcon(m_ImageList, hIcon);
  725. DestroyIcon(hIcon);
  726. }
  727. if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DRIVERBLOCK))) != NULL) {
  728. DriverBlockIndex = ImageList_AddIcon(m_ImageList, hIcon);
  729. DestroyIcon(hIcon);
  730. }
  731. }
  732. //
  733. //Initialize the list of drivers
  734. //
  735. LV_COLUMN lvcCol;
  736. LV_ITEM lviItem;
  737. CDriverFile* pDrvFile;
  738. PVOID Context;
  739. HWND hwndFileList = GetDlgItem(m_hDlg, IDC_DRIVERFILES_FILELIST);
  740. //
  741. // Insert a single column for this list.
  742. //
  743. lvcCol.mask = LVCF_FMT | LVCF_WIDTH;
  744. lvcCol.fmt = LVCFMT_LEFT;
  745. lvcCol.iSubItem = 0;
  746. ListView_InsertColumn(hwndFileList, 0, (LV_COLUMN FAR *)&lvcCol);
  747. ListView_SetExtendedListViewStyle(hwndFileList, LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);
  748. if (m_ImageList) {
  749. ListView_SetImageList(hwndFileList, m_ImageList, LVSIL_SMALL);
  750. }
  751. ListView_DeleteAllItems(hwndFileList);
  752. if (m_pDriver && m_pDriver->GetFirstDriverFile(&pDrvFile, Context)) {
  753. do {
  754. ASSERT(pDrvFile);
  755. LPCTSTR pFullPathName;
  756. pFullPathName = pDrvFile->GetFullPathName();
  757. if (pFullPathName) {
  758. lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  759. lviItem.iSubItem = 0;
  760. lviItem.lParam = (LPARAM)pDrvFile;
  761. lviItem.iItem = ListView_GetItemCount(hwndFileList);
  762. lviItem.pszText = (LPTSTR)pFullPathName;
  763. if (m_ImageList) {
  764. if (pDrvFile->IsDriverBlocked()) {
  765. //
  766. // The driver is blocked
  767. //
  768. lviItem.iImage = DriverBlockIndex;
  769. } else if (pDrvFile->GetWin32Error() == NO_ERROR) {
  770. //
  771. // The driver is WHQL signed.
  772. //
  773. lviItem.iImage = SignedIndex;
  774. } else if ((pDrvFile->GetWin32Error() == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  775. (pDrvFile->GetWin32Error() == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  776. //
  777. // The driver is Authenticode signed.
  778. //
  779. lviItem.iImage = CertIndex;
  780. } else {
  781. //
  782. // The driver is NOT blocked and NOT signed.
  783. //
  784. lviItem.iImage = BlankIndex;
  785. }
  786. }
  787. ListView_InsertItem(hwndFileList, &lviItem);
  788. }
  789. } while (m_pDriver->GetNextDriverFile(&pDrvFile, Context));
  790. if (ListView_GetItemCount(hwndFileList) >= 1) {
  791. ListView_SetItemState(hwndFileList,
  792. 0,
  793. LVIS_SELECTED | LVIS_FOCUSED,
  794. LVIS_SELECTED | LVIS_FOCUSED
  795. );
  796. ListView_EnsureVisible(hwndFileList, 0, FALSE);
  797. ListView_SetColumnWidth(hwndFileList, 0, LVSCW_AUTOSIZE_USEHEADER);
  798. ShowCurDriverFileDetail();
  799. } else {
  800. //
  801. // nothing on the driver file list, disable it
  802. //
  803. ::EnableWindow(GetControl(IDC_DRIVERFILES_FILELIST), FALSE);
  804. }
  805. }
  806. }
  807. catch (CMemoryException* e) {
  808. e->Delete();
  809. return FALSE;
  810. }
  811. return TRUE;
  812. }
  813. void
  814. CDriverFilesDlg::OnCommand(
  815. WPARAM wParam,
  816. LPARAM lParam
  817. )
  818. {
  819. UNREFERENCED_PARAMETER(lParam);
  820. if (BN_CLICKED == HIWORD(wParam)) {
  821. if (IDOK == LOWORD(wParam)) {
  822. EndDialog(m_hDlg, IDOK);
  823. } else if (IDCANCEL == LOWORD(wParam)) {
  824. EndDialog(m_hDlg, IDCANCEL);
  825. }
  826. }
  827. }
  828. BOOL
  829. CDriverFilesDlg::OnNotify(
  830. LPNMHDR pnmhdr
  831. )
  832. {
  833. switch (pnmhdr->code) {
  834. case LVN_ITEMCHANGED:
  835. ShowCurDriverFileDetail();
  836. break;
  837. case NM_RETURN:
  838. case NM_CLICK:
  839. if (pnmhdr->idFrom == IDS_DRIVERFILES_BLOCKDRIVERLINK) {
  840. LaunchHelpForBlockedDriver();
  841. }
  842. break;
  843. }
  844. return FALSE;
  845. }
  846. BOOL
  847. CDriverFilesDlg::OnDestroy()
  848. {
  849. HICON hIcon;
  850. hIcon = (HICON)SendDlgItemMessage(m_hDlg, IDC_DRIVERFILES_ICON, STM_GETICON, 0, 0);
  851. if (hIcon) {
  852. DestroyIcon(hIcon);
  853. }
  854. if (m_ImageList) {
  855. ImageList_Destroy(m_ImageList);
  856. }
  857. return FALSE;
  858. }
  859. BOOL
  860. CDriverFilesDlg::OnHelp(
  861. LPHELPINFO pHelpInfo
  862. )
  863. {
  864. WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
  865. (ULONG_PTR)g_a110HelpIDs);
  866. return FALSE;
  867. }
  868. BOOL
  869. CDriverFilesDlg::OnContextMenu(
  870. HWND hWnd,
  871. WORD xPos,
  872. WORD yPos
  873. )
  874. {
  875. UNREFERENCED_PARAMETER(xPos);
  876. UNREFERENCED_PARAMETER(yPos);
  877. WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
  878. (ULONG_PTR)g_a110HelpIDs);
  879. return FALSE;
  880. }
  881. void
  882. CDriverFilesDlg::ShowCurDriverFileDetail()
  883. {
  884. HWND hwndFileList = GetDlgItem(m_hDlg, IDC_DRIVERFILES_FILELIST);
  885. LVITEM lvItem;
  886. LPCTSTR pString;
  887. lvItem.mask = LVIF_PARAM;
  888. lvItem.iSubItem = 0;
  889. lvItem.iItem = ListView_GetNextItem(hwndFileList,
  890. -1,
  891. LVNI_SELECTED
  892. );
  893. if (lvItem.iItem != -1) {
  894. try {
  895. ListView_GetItem(hwndFileList, &lvItem);
  896. CDriverFile* pDrvFile = (CDriverFile*)lvItem.lParam;
  897. ASSERT(pDrvFile);
  898. TCHAR TempString[LINE_LEN];
  899. LPCTSTR pFullPathName;
  900. pFullPathName = pDrvFile->GetFullPathName();
  901. if (!pFullPathName || (pDrvFile->GetAttributes() == 0xFFFFFFFF)) {
  902. //
  903. // This is the case when the file is not present on the system
  904. //
  905. LoadResourceString(IDS_NOT_PRESENT, TempString, ARRAYLEN(TempString));
  906. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, TempString);
  907. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, TempString);
  908. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, TempString);
  909. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DIGITALSIGNER, TempString);
  910. ShowWindow(GetControl(IDS_DRIVERFILES_BLOCKDRIVERLINK), FALSE);
  911. } else {
  912. if (!pDrvFile->HasVersionInfo()) {
  913. //
  914. // This is the case when the file is present but it does not have
  915. // version information.
  916. //
  917. LoadResourceString(IDS_UNKNOWN, TempString, ARRAYLEN(TempString));
  918. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, TempString);
  919. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, TempString);
  920. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, TempString);
  921. } else {
  922. //
  923. // Show the file version information.
  924. //
  925. TempString[0] = _T('\0');
  926. pString = pDrvFile->GetVersion();
  927. if (!pString && _T('\0') == TempString[0]) {
  928. LoadResourceString(IDS_NOT_AVAILABLE, TempString, ARRAYLEN(TempString));
  929. pString = TempString;
  930. }
  931. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, (LPTSTR)pString);
  932. pString = pDrvFile->GetProvider();
  933. if (!pString && _T('\0') == TempString[0]) {
  934. LoadResourceString(IDS_NOT_AVAILABLE, TempString, ARRAYLEN(TempString));
  935. pString = TempString;
  936. }
  937. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, (LPTSTR)pString);
  938. pString = pDrvFile->GetCopyright();
  939. if (!pString && _T('\0') == TempString[0]) {
  940. LoadResourceString(IDS_NOT_AVAILABLE, TempString, ARRAYLEN(TempString));
  941. pString = TempString;
  942. }
  943. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, (LPTSTR)pString);
  944. }
  945. //
  946. // Show the digital signer if the file is signed.
  947. //
  948. pString = pDrvFile->GetInfDigitalSigner();
  949. if (!pString) {
  950. TempString[0] = _T('\0');
  951. LoadResourceString(((pDrvFile->GetWin32Error() != 0) &&
  952. (pDrvFile->GetWin32Error() != 0xFFFFFFFF) &&
  953. (pDrvFile->GetWin32Error() != ERROR_DRIVER_BLOCKED))
  954. ? IDS_NO_DIGITALSIGNATURE
  955. : IDS_NOT_AVAILABLE,
  956. TempString,
  957. ARRAYLEN(TempString));
  958. pString = TempString;
  959. }
  960. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DIGITALSIGNER, (LPTSTR)pString);
  961. //
  962. // Show the block driver link if this driver is blocked and it
  963. // has a block driver html help ID.
  964. //
  965. ShowWindow(GetControl(IDS_DRIVERFILES_BLOCKDRIVERLINK),
  966. pDrvFile->GetBlockedDriverHtmlHelpID()
  967. ? TRUE
  968. : FALSE);
  969. }
  970. }
  971. catch (CMemoryException* e) {
  972. e->Delete();
  973. // report memory error
  974. MsgBoxParam(m_hDlg, 0, 0, 0);
  975. }
  976. } else {
  977. // no selection
  978. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, TEXT(""));
  979. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, TEXT(""));
  980. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, TEXT(""));
  981. SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DIGITALSIGNER, TEXT(""));
  982. }
  983. }
  984. void
  985. CDriverFilesDlg::LaunchHelpForBlockedDriver()
  986. {
  987. HWND hwndFileList = GetDlgItem(m_hDlg, IDC_DRIVERFILES_FILELIST);
  988. LVITEM lvItem;
  989. LPCTSTR pHtmlHelpID;
  990. String strHcpLink;
  991. lvItem.mask = LVIF_PARAM;
  992. lvItem.iSubItem = 0;
  993. lvItem.iItem = ListView_GetNextItem(hwndFileList,
  994. -1,
  995. LVNI_SELECTED
  996. );
  997. if (lvItem.iItem != -1) {
  998. try {
  999. ListView_GetItem(hwndFileList, &lvItem);
  1000. CDriverFile* pDrvFile = (CDriverFile*)lvItem.lParam;
  1001. ASSERT(pDrvFile);
  1002. if ((pHtmlHelpID = pDrvFile->GetBlockedDriverHtmlHelpID()) != NULL) {
  1003. strHcpLink.Format(TEXT("HELPCTR.EXE -url %s"), pHtmlHelpID);
  1004. ShellExecute(m_hDlg,
  1005. TEXT("open"),
  1006. TEXT("HELPCTR.EXE"),
  1007. (LPTSTR)strHcpLink,
  1008. NULL,
  1009. SW_SHOWNORMAL);
  1010. }
  1011. }
  1012. catch (CMemoryException* e) {
  1013. e->Delete();
  1014. // report memory error
  1015. MsgBoxParam(m_hDlg, 0, 0, 0);
  1016. }
  1017. }
  1018. }