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.

1212 lines
37 KiB

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