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.

833 lines
26 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. devgenpg.cpp
  5. Abstract:
  6. This module implements CDeviceGeneralPage -- device general property page
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. // devgenpg.cpp : implementation file
  12. //
  13. #include "devmgr.h"
  14. #include "hwprof.h"
  15. #include "devgenpg.h"
  16. #include "tswizard.h"
  17. #include "utils.h"
  18. //
  19. // help topic ids
  20. //
  21. const DWORD g_a103HelpIDs[]=
  22. {
  23. IDC_DEVGEN_TITLE_TYPE, idh_devmgr_general_devicetype,
  24. IDC_DEVGEN_TITLE_MFG, idh_devmgr_general_manufacturer,
  25. IDC_DEVGEN_STATUSGROUP, IDH_DISABLEHELP,
  26. IDC_DEVGEN_ICON, IDH_DISABLEHELP, // General: "" (Static)
  27. IDC_DEVGEN_DESC, IDH_DISABLEHELP, // General: "" (Static)
  28. IDC_DEVGEN_USAGETEXT, IDH_DISABLEHELP, // General: "Place a check mark next to the configuration(s) where this device should be used." (Static)
  29. IDC_DEVGEN_TYPE, idh_devmgr_general_devicetype, // General: "" (Static)
  30. IDC_DEVGEN_MFG, idh_devmgr_general_manufacturer, // General: "" (Static)
  31. IDC_DEVGEN_STATUS, idh_devmgr_general_device_status, // General: "" (Static)
  32. IDC_DEVGEN_PROFILELIST, idh_devmgr_general_device_usage, // General: "Dropdown Combo" (SysListView32)
  33. IDC_DEVGEN_TITLE_LOCATION, idh_devmgr_general_location, // General: location
  34. IDC_DEVGEN_LOCATION, idh_devmgr_general_location, // General: location
  35. IDC_DEVGEN_TROUBLESHOOTING, idh_devmgr_general_trouble, // General: troubleshooting
  36. 0, 0
  37. };
  38. CDeviceGeneralPage::~CDeviceGeneralPage()
  39. {
  40. if (m_pHwProfileList) {
  41. delete m_pHwProfileList;
  42. }
  43. if (m_pProblemAgent) {
  44. delete m_pProblemAgent;
  45. }
  46. }
  47. HPROPSHEETPAGE
  48. CDeviceGeneralPage::Create(
  49. CDevice* pDevice
  50. )
  51. {
  52. ASSERT(pDevice);
  53. if (pDevice)
  54. {
  55. m_pDevice = pDevice;
  56. // override PROPSHEETPAGE structure here...
  57. m_psp.lParam = (LPARAM)this;
  58. pDevice->m_pMachine->DiTurnOffDiExFlags(*pDevice, DI_FLAGSEX_PROPCHANGE_PENDING);
  59. return CreatePage();
  60. }
  61. return NULL;
  62. }
  63. BOOL
  64. CDeviceGeneralPage::OnInitDialog(
  65. LPPROPSHEETPAGE ppsp
  66. )
  67. {
  68. m_pDevice->m_pMachine->AttachPropertySheet(m_hDlg);
  69. // notify property sheet data that the property sheet is up
  70. m_pDevice->m_psd.PageCreateNotify(m_hDlg);
  71. return CPropSheetPage::OnInitDialog(ppsp);
  72. }
  73. BOOL
  74. CDeviceGeneralPage::OnApply()
  75. {
  76. try
  77. {
  78. HWND hwndCB = GetControl(IDC_DEVGEN_PROFILELIST);
  79. m_SelectedDeviceUsage = ComboBox_GetCurSel(hwndCB);
  80. if ((-1 != m_SelectedDeviceUsage) &&
  81. (m_SelectedDeviceUsage != m_CurrentDeviceUsage)) {
  82. //
  83. // User is changing the device usage
  84. //
  85. UpdateHwProfileStates();
  86. SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  87. return TRUE;
  88. }
  89. }
  90. catch(CMemoryException* e)
  91. {
  92. e->Delete();
  93. MsgBoxParam(m_hDlg, 0, 0, 0);
  94. }
  95. return FALSE;
  96. }
  97. void
  98. CDeviceGeneralPage::UpdateHwProfileStates()
  99. {
  100. // first decide what to do(enabling or disabling or both)
  101. BOOL Canceled;
  102. Canceled = FALSE;
  103. if (m_SelectedDeviceUsage == m_CurrentDeviceUsage) {
  104. return;
  105. }
  106. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_NODI_DEFAULTACTION);
  107. SP_PROPCHANGE_PARAMS pcp;
  108. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  109. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  110. //
  111. // specific enabling/disabling
  112. //
  113. pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
  114. CHwProfile* phwpf;
  115. if (m_pHwProfileList->GetCurrentHwProfile(&phwpf))
  116. {
  117. pcp.StateChange = DICS_DISABLE;
  118. if (DEVICE_ENABLE == m_SelectedDeviceUsage) {
  119. pcp.StateChange = DICS_ENABLE;
  120. }
  121. pcp.HwProfile = phwpf->GetHwProfile();
  122. m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice,
  123. &pcp.ClassInstallHeader,
  124. sizeof(pcp)
  125. );
  126. m_pDevice->m_pMachine->DiCallClassInstaller(DIF_PROPERTYCHANGE, *m_pDevice);
  127. Canceled = (ERROR_CANCELLED == GetLastError());
  128. }
  129. //
  130. // class installer has not objection of our enabling/disabling,
  131. // do real enabling/disabling.
  132. //
  133. if (!Canceled)
  134. {
  135. if (m_pHwProfileList->GetCurrentHwProfile(&phwpf))
  136. {
  137. if (DEVICE_ENABLE == m_SelectedDeviceUsage)
  138. {
  139. //
  140. // we are enabling the device,
  141. // do a specific enabling then a globally enabling.
  142. // the globally enabling will start the device
  143. // The implementation here is different from
  144. // Win9x which does a global enabling, a config
  145. // specific enabling and then a start.
  146. //
  147. pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
  148. pcp.HwProfile = phwpf->GetHwProfile();
  149. m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice,
  150. &pcp.ClassInstallHeader,
  151. sizeof(pcp)
  152. );
  153. m_pDevice->m_pMachine->DiChangeState(*m_pDevice);
  154. //
  155. // this call will start the device is it not started.
  156. //
  157. pcp.Scope = DICS_FLAG_GLOBAL;
  158. m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice,
  159. &pcp.ClassInstallHeader,
  160. sizeof(pcp)
  161. );
  162. m_pDevice->m_pMachine->DiChangeState(*m_pDevice);
  163. }
  164. else
  165. {
  166. //
  167. // Do either a global disable or a configspecific disable
  168. //
  169. if (DEVICE_DISABLE == m_SelectedDeviceUsage) {
  170. pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
  171. } else {
  172. pcp.Scope = DICS_FLAG_GLOBAL;
  173. }
  174. pcp.StateChange = DICS_DISABLE;
  175. pcp.HwProfile = phwpf->GetHwProfile();
  176. m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice,
  177. &pcp.ClassInstallHeader,
  178. sizeof(pcp)
  179. );
  180. m_pDevice->m_pMachine->DiChangeState(*m_pDevice);
  181. }
  182. }
  183. // signal that the property of the device is changed.
  184. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
  185. m_RestartFlags |= (m_pDevice->m_pMachine->DiGetFlags(*m_pDevice)) & (DI_NEEDRESTART | DI_NEEDREBOOT);
  186. }
  187. // remove class install parameters, this also reset
  188. // DI_CLASSINATLLPARAMS
  189. m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice, NULL, 0);
  190. m_pDevice->m_pMachine->DiTurnOffDiFlags(*m_pDevice, DI_NODI_DEFAULTACTION);
  191. }
  192. BOOL
  193. CDeviceGeneralPage::OnLastChanceApply()
  194. {
  195. //
  196. // The last chance apply message is sent in reverse order page n to page 0.
  197. //
  198. // Since we are the first page in the set of property sheets we can gaurentee
  199. // that the last PSN_LASTCHANCEAPPLY message will be the last message for all
  200. // the pages.
  201. //
  202. // The property sheet is going away, consolidate the changes on the device. We
  203. // do this during the PSN_LASTCHANCEAPPLY message so that the property sheet is
  204. // still displayed while we do the DIF_PROPERTYCHANGE. There are some cases where
  205. // the DIF_PROPERTYCHANGE can take quite a long time so we want the property sheet
  206. // to still be shown while this is happening. If we do this during the DestroyCallback
  207. // the property sheet UI has already been torn down and so the user won't realize
  208. // we are still saving the changes.
  209. //
  210. try
  211. {
  212. ASSERT(m_pDevice);
  213. if (m_pDevice->m_pMachine->DiGetExFlags(*m_pDevice) & DI_FLAGSEX_PROPCHANGE_PENDING)
  214. {
  215. DWORD Status = 0, Problem = 0;
  216. //
  217. // If the device has the DN_WILL_BE_REMOVED flag set and the user is
  218. // attempting to change settings on the driver then we will prompt them for a
  219. // reboot and include text in the prompt that explains this device
  220. // is in the process of being removed.
  221. //
  222. if (m_pDevice->GetStatus(&Status, &Problem) &&
  223. (Status & DN_WILL_BE_REMOVED)) {
  224. PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_CHANGE_SETTINGS);
  225. } else {
  226. //
  227. // property change pending, issue a DICS_PROPERTYCHANGE to the
  228. // class installer. A DICS_PROPCHANGE would basically stop the
  229. // device and restart it. If each property page issues
  230. // its own DICS_PROPCHANGE command, the device would
  231. // be stopped/started several times even though one is enough.
  232. // A property page sets DI_FLAGEX_PROPCHANGE_PENDING when it needs
  233. // a DICS_PROPCHANGE command to be issued.
  234. //
  235. SP_PROPCHANGE_PARAMS pcp;
  236. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  237. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  238. HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  239. pcp.Scope = DICS_FLAG_GLOBAL;
  240. pcp.StateChange = DICS_PROPCHANGE;
  241. m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice,
  242. &pcp.ClassInstallHeader,
  243. sizeof(pcp)
  244. );
  245. m_pDevice->m_pMachine->DiCallClassInstaller(DIF_PROPERTYCHANGE, *m_pDevice);
  246. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
  247. m_pDevice->m_pMachine->DiTurnOffDiExFlags(*m_pDevice, DI_FLAGSEX_PROPCHANGE_PENDING);
  248. if (hCursorOld) {
  249. SetCursor(hCursorOld);
  250. }
  251. }
  252. }
  253. }
  254. catch(CMemoryException* e)
  255. {
  256. e->Delete();
  257. MsgBoxParam(m_hDlg, 0, 0, 0);
  258. }
  259. return FALSE;
  260. }
  261. UINT
  262. CDeviceGeneralPage::DestroyCallback()
  263. {
  264. //
  265. // We do this because this is the page we are sure will be created --
  266. // this page is ALWAYS the first page.
  267. //
  268. ASSERT(m_pDevice);
  269. m_RestartFlags |= m_pDevice->m_pMachine->DiGetFlags(*m_pDevice);
  270. if (m_RestartFlags & (DI_NEEDRESTART | DI_NEEDREBOOT))
  271. {
  272. //
  273. // Do not use our window handle(or its parent) as the parent
  274. // to the newly create dialog because they are in "detroyed state".
  275. // WM_CLOSE does not help either.
  276. // NULL window handle(Desktop) should be okay here.
  277. //
  278. // We only want to prompt for a restart if device manager is connected
  279. // to the local machine.
  280. //
  281. if (m_pDevice->m_pMachine->IsLocal())
  282. {
  283. if (PromptForRestart(NULL, m_RestartFlags) == IDNO) {
  284. if (m_pDevice->m_pMachine->m_ParentMachine) {
  285. m_pDevice->m_pMachine->m_ParentMachine->ScheduleRefresh();
  286. } else {
  287. m_pDevice->m_pMachine->ScheduleRefresh();
  288. }
  289. }
  290. }
  291. }
  292. // notify CPropSheetData that the property sheet is going away
  293. m_pDevice->m_psd.PageDestroyNotify(m_hDlg);
  294. if (m_RestartFlags & DI_PROPERTIES_CHANGE)
  295. {
  296. // Device properties changed. We need to refresh the machine.
  297. // Since we are running in a separate thread, we can not
  298. // call the refresh function, instead, we schedule it.
  299. // This should be done before enabling the refresh
  300. m_pDevice->m_pMachine->ScheduleRefresh();
  301. }
  302. //
  303. // Detach this property page from the CMachine so that the CMachine can be
  304. // destroyed now if it needs to be.
  305. //
  306. m_pDevice->m_pMachine->DetachPropertySheet(m_hDlg);
  307. ASSERT(!::IsWindow(m_hwndLocationTip));
  308. //
  309. // Destory the CMachine.
  310. //
  311. CMachine* pMachine;
  312. pMachine = m_pDevice->m_pMachine;
  313. if (pMachine->ShouldPropertySheetDestroy()) {
  314. delete pMachine;
  315. }
  316. return CPropSheetPage::DestroyCallback();
  317. }
  318. void
  319. CDeviceGeneralPage::UpdateControls(
  320. LPARAM lParam
  321. )
  322. {
  323. if (lParam)
  324. m_pDevice = (CDevice*)lParam;
  325. m_RestartFlags = 0;
  326. try
  327. {
  328. //
  329. // Calling PropertyChanged() will update the display name for the device. We need
  330. // to do this in case a 3rd party property sheet did something that could change
  331. // the device's display name.
  332. //
  333. m_pDevice->PropertyChanged();
  334. SetDlgItemText(m_hDlg, IDC_DEVGEN_DESC, m_pDevice->GetDisplayName());
  335. TCHAR TempString[512];
  336. String str;
  337. m_pDevice->GetMFGString(str);
  338. SetDlgItemText(m_hDlg, IDC_DEVGEN_MFG, str);
  339. SetDlgItemText(m_hDlg, IDC_DEVGEN_TYPE, m_pDevice->GetClassDisplayName());
  340. HICON hIconNew;
  341. hIconNew = m_pDevice->LoadClassIcon();
  342. if (hIconNew)
  343. {
  344. HICON hIconOld;
  345. m_IDCicon = IDC_DEVGEN_ICON; // Save for cleanup in OnDestroy.
  346. hIconOld = (HICON)SendDlgItemMessage(m_hDlg, IDC_DEVGEN_ICON,
  347. STM_SETICON, (WPARAM)hIconNew,
  348. 0);
  349. if (hIconOld)
  350. DestroyIcon(hIconOld);
  351. }
  352. //
  353. // get the device location information
  354. //
  355. if (::GetLocationInformation(m_pDevice->GetDevNode(),
  356. TempString,
  357. ARRAYLEN(TempString),
  358. m_pDevice->m_pMachine->GetHMachine()) != CR_SUCCESS)
  359. {
  360. // if the devnode does not have location information,
  361. // use the word "unknown"
  362. LoadString(g_hInstance, IDS_UNKNOWN, TempString, ARRAYLEN(TempString));
  363. }
  364. SetDlgItemText(m_hDlg, IDC_DEVGEN_LOCATION, TempString);
  365. AddToolTips(m_hDlg, IDC_DEVGEN_LOCATION, TempString, &m_hwndLocationTip);
  366. ShowWindow(GetControl(IDC_DEVGEN_TROUBLESHOOTING), SW_HIDE);
  367. DWORD Problem, Status;
  368. if (m_pDevice->GetStatus(&Status, &Problem) || m_pDevice->IsPhantom())
  369. {
  370. //
  371. // if the device is a phantom device, use the CM_PROB_PHANTOM
  372. //
  373. if (m_pDevice->IsPhantom())
  374. {
  375. Problem = CM_PROB_PHANTOM;
  376. Status = DN_HAS_PROBLEM;
  377. }
  378. //
  379. // if the device is not started and no problem is assigned to it
  380. // fake the problem number to be failed start.
  381. //
  382. if (!(Status & DN_STARTED) && !Problem && m_pDevice->IsRAW())
  383. {
  384. Problem = CM_PROB_FAILED_START;
  385. }
  386. //
  387. // if a device has a private problem then give it special text telling
  388. // the user to contact the manufacturer of this driver.
  389. //
  390. if (Status & DN_PRIVATE_PROBLEM)
  391. {
  392. str.LoadString(g_hInstance, IDS_SPECIALPROB_PRIVATEPROB);
  393. }
  394. //
  395. // if a device is not started and still does not have a problem
  396. // then give it special problem text saying that this device
  397. // does not have a driver.
  398. //
  399. else if (!(Status & DN_STARTED) && !(Status & DN_HAS_PROBLEM))
  400. {
  401. if (::GetSystemMetrics(SM_CLEANBOOT) == 0) {
  402. str.LoadString(g_hInstance, IDS_SPECIALPROB_NODRIVERS);
  403. } else {
  404. str.LoadString(g_hInstance, IDS_SPECIALPROB_SAFEMODE);
  405. }
  406. }
  407. //
  408. // Display normal problem text
  409. //
  410. else
  411. {
  412. UINT len = GetDeviceProblemText((HMACHINE)(*m_pDevice->m_pMachine),
  413. m_pDevice->GetDevNode(), Problem, TempString, ARRAYLEN(TempString));
  414. if (len)
  415. {
  416. if (len < ARRAYLEN(TempString))
  417. {
  418. SetDlgItemText(m_hDlg, IDC_DEVGEN_STATUS, TempString);
  419. str = TempString;
  420. }
  421. else
  422. {
  423. BufferPtr<TCHAR> TextPtr(len + 1);
  424. GetDeviceProblemText((HMACHINE)(*m_pDevice->m_pMachine),
  425. m_pDevice->GetDevNode(), Problem, TextPtr, len + 1);
  426. str = (LPTSTR)TextPtr;
  427. }
  428. }
  429. else
  430. {
  431. str.LoadString(g_hInstance, IDS_PROB_UNKNOWN);
  432. }
  433. }
  434. //
  435. // Add the 'related driver blocked' text if the device has the devnode
  436. // flag DN_DRIVER_BLOCKED set and it does not have the problem
  437. // CM_PROB_DRIVER_BLOCKED.
  438. //
  439. if ((Status & DN_DRIVER_BLOCKED) &&
  440. (Problem != CM_PROB_DRIVER_BLOCKED)) {
  441. LoadString(g_hInstance, IDS_DRIVER_BLOCKED, TempString, ARRAYLEN(TempString));
  442. str += TempString;
  443. }
  444. //
  445. // Add the 'will be removed' text if the device is going to be removed
  446. // on the next restart.
  447. //
  448. if (Status & DN_WILL_BE_REMOVED) {
  449. LoadString(g_hInstance, IDS_WILL_BE_REMOVED, TempString, ARRAYLEN(TempString));
  450. str += TempString;
  451. }
  452. //
  453. // Add the restart text if the device needs to be restarted
  454. //
  455. if (Status & DN_NEED_RESTART) {
  456. LoadString(g_hInstance, IDS_NEED_RESTART, TempString, ARRAYLEN(TempString));
  457. str += TempString;
  458. m_RestartFlags |= DI_NEEDRESTART;
  459. }
  460. //
  461. // Create the problem agent and update the control text
  462. //
  463. if (!(Status & DN_PRIVATE_PROBLEM))
  464. {
  465. if (m_pProblemAgent) {
  466. delete m_pProblemAgent;
  467. }
  468. m_pProblemAgent = new CProblemAgent(m_pDevice, Problem, FALSE);
  469. DWORD Len;
  470. Len = m_pProblemAgent->InstructionText(TempString, ARRAYLEN(TempString));
  471. if (Len)
  472. {
  473. str += TempString;
  474. }
  475. Len = m_pProblemAgent->FixitText(TempString, ARRAYLEN(TempString));
  476. if (Len)
  477. {
  478. ::ShowWindow(GetControl(IDC_DEVGEN_TROUBLESHOOTING), SW_SHOW);
  479. SetDlgItemText(m_hDlg, IDC_DEVGEN_TROUBLESHOOTING, TempString);
  480. }
  481. }
  482. }
  483. else
  484. {
  485. TRACE((TEXT("%s has not status, devnode =%lx, cr = %lx\n"),
  486. m_pDevice->GetDisplayName(), m_pDevice->GetDevNode(),
  487. m_pDevice->m_pMachine->GetLastCR()));
  488. str.LoadString(g_hInstance, IDS_PROB_UNKNOWN);
  489. ::ShowWindow(GetControl(IDC_DEVGEN_TROUBLESHOOTING), SW_HIDE);
  490. }
  491. SetDlgItemText(m_hDlg, IDC_DEVGEN_STATUS, str);
  492. HWND hWnd = GetControl(IDC_DEVGEN_PROFILELIST);
  493. if (m_pDevice->NoChangeUsage() ||
  494. !m_pDevice->IsDisableable() ||
  495. (CM_PROB_HARDWARE_DISABLED == Problem))
  496. {
  497. // the device disallows any changes on hw profile.
  498. // disable all profile related controls.
  499. ::EnableWindow(GetControl(IDC_DEVGEN_PROFILELIST), FALSE);
  500. ::EnableWindow(GetControl(IDC_DEVGEN_USAGETEXT), FALSE);
  501. }
  502. else
  503. {
  504. HWND hwndCB = GetControl(IDC_DEVGEN_PROFILELIST);
  505. DWORD ConfigFlags;
  506. if (!m_pDevice->GetConfigFlags(&ConfigFlags)) {
  507. ConfigFlags = 0;
  508. }
  509. //
  510. // only want the disabled bit
  511. //
  512. ConfigFlags &= CONFIGFLAG_DISABLED;
  513. //
  514. // rebuild the profile list.
  515. //
  516. if (m_pHwProfileList) {
  517. delete m_pHwProfileList;
  518. }
  519. m_pHwProfileList = new CHwProfileList();
  520. if (m_pHwProfileList->Create(m_pDevice, ConfigFlags))
  521. {
  522. ComboBox_ResetContent(hwndCB);
  523. //
  524. // Get the current device usage
  525. //
  526. if (m_pDevice->IsStateDisabled()) {
  527. if ((m_pHwProfileList->GetCount() > 1) && ConfigFlags) {
  528. m_CurrentDeviceUsage = DEVICE_DISABLE_GLOBAL;
  529. } else {
  530. m_CurrentDeviceUsage = DEVICE_DISABLE;
  531. }
  532. } else {
  533. m_CurrentDeviceUsage = DEVICE_ENABLE;
  534. }
  535. //
  536. // Always add the Enable item
  537. //
  538. String Enable;
  539. Enable.LoadString(g_hInstance, IDS_ENABLE_CURRENT);
  540. ComboBox_AddString(hwndCB, Enable);
  541. //
  542. // Add the disable items. There will either be one disable
  543. // item if there is only one hardware profile or two if there
  544. // are more than one hardware profile.
  545. //
  546. if (m_pHwProfileList->GetCount() > 1) {
  547. String DisableInCurrent;
  548. DisableInCurrent.LoadString(g_hInstance, IDS_DISABLE_IN_PROFILE);
  549. ComboBox_AddString(hwndCB, DisableInCurrent);
  550. String DisableGlobal;
  551. DisableGlobal.LoadString(g_hInstance, IDS_DISABLE_GLOBAL);
  552. ComboBox_AddString(hwndCB, DisableGlobal);
  553. } else {
  554. String Disable;
  555. Disable.LoadString(g_hInstance, IDS_DISABLE_CURRENT);
  556. ComboBox_AddString(hwndCB, Disable);
  557. }
  558. ComboBox_SetCurSel(hwndCB, m_CurrentDeviceUsage);
  559. }
  560. }
  561. //
  562. // If this is a remote computer or the user does not have SE_LOAD_DRIVER_NAME
  563. // privileges then disable the enable/disable drop down list along with the
  564. // TroubleShooter button.
  565. //
  566. if (!m_pDevice->m_pMachine->IsLocal() ||
  567. !g_HasLoadDriverNamePrivilege)
  568. {
  569. ::EnableWindow(GetControl(IDC_DEVGEN_PROFILELIST), FALSE);
  570. ::EnableWindow(GetControl(IDC_DEVGEN_TROUBLESHOOTING), FALSE);
  571. }
  572. //
  573. // Check if we need to autolauch the troubleshooter
  574. //
  575. if (m_pDevice->m_pMachine->IsLocal() &&
  576. g_HasLoadDriverNamePrivilege &&
  577. m_pDevice->m_bLaunchTroubleShooter) {
  578. m_pDevice->m_bLaunchTroubleShooter = FALSE;
  579. ::PostMessage(m_hDlg, WM_COMMAND, MAKELONG(IDC_DEVGEN_TROUBLESHOOTING, BN_CLICKED, ), 0);
  580. }
  581. }
  582. catch (CMemoryException* e)
  583. {
  584. e->Delete();
  585. MsgBoxParam(m_hDlg, 0, 0, 0);
  586. }
  587. }
  588. BOOL
  589. CDeviceGeneralPage::OnQuerySiblings(
  590. WPARAM wParam,
  591. LPARAM lParam
  592. )
  593. {
  594. DMQUERYSIBLINGCODE Code = (DMQUERYSIBLINGCODE)wParam;
  595. if (QSC_TO_FOREGROUND == Code)
  596. {
  597. HWND hwndSheet;
  598. hwndSheet = m_pDevice->m_psd.GetWindowHandle();
  599. if (GetForegroundWindow() != hwndSheet)
  600. {
  601. SetForegroundWindow(hwndSheet);
  602. }
  603. SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, 1);
  604. return TRUE;
  605. }
  606. return CPropSheetPage::OnQuerySiblings(wParam, lParam);
  607. }
  608. BOOL
  609. CDeviceGeneralPage::OnCommand(
  610. WPARAM wParam,
  611. LPARAM lParam
  612. )
  613. {
  614. if (BN_CLICKED == HIWORD(wParam) &&
  615. IDC_DEVGEN_TROUBLESHOOTING == LOWORD(wParam)) {
  616. BOOL fChanged = FALSE;
  617. if (m_pProblemAgent) {
  618. fChanged = m_pProblemAgent->FixIt(GetParent(m_hDlg));
  619. }
  620. if (fChanged) {
  621. m_pDevice->PropertyChanged();
  622. m_pDevice->GetClass()->PropertyChanged();
  623. m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
  624. UpdateControls();
  625. PropSheet_SetTitle(GetParent(m_hDlg), PSH_PROPTITLE, m_pDevice->GetDisplayName());
  626. PropSheet_CancelToClose(GetParent(m_hDlg));
  627. //
  628. // ISSUE: JasonC 2/7/2000
  629. //
  630. // A refresh on m_pDevice->m_pMachine is necessary here.
  631. // Since we are running on a different thread and each
  632. // property page may have cached the HDEVINFO and the
  633. // SP_DEVINFO_DATA, refresh on the CMachine object can not
  634. // be done here. The problem is worsen by the fact that
  635. // user can go back to the device tree and work on the tree
  636. // while this property sheet is still up.
  637. // It would be nice if MMC would support modal dialog boxes.
  638. //
  639. }
  640. }
  641. return FALSE;
  642. }
  643. BOOL
  644. CDeviceGeneralPage::OnHelp(
  645. LPHELPINFO pHelpInfo
  646. )
  647. {
  648. WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
  649. (ULONG_PTR)g_a103HelpIDs);
  650. return FALSE;
  651. }
  652. BOOL
  653. CDeviceGeneralPage::OnContextMenu(
  654. HWND hWnd,
  655. WORD xPos,
  656. WORD yPos
  657. )
  658. {
  659. WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
  660. (ULONG_PTR)g_a103HelpIDs);
  661. return FALSE;
  662. }