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.

926 lines
25 KiB

  1. #include "stdafx.h"
  2. #include "PageServices.h"
  3. #include "MSConfigState.h"
  4. #include "EssentialSvcDlg.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. // This array contains the list of essential services. These must be in
  11. // lower case (for a caseless comparison).
  12. LPCTSTR aszEssentialServices[] =
  13. {
  14. _T("rpclocator"),
  15. _T("rpcss"),
  16. NULL
  17. };
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CPageServices property page
  20. IMPLEMENT_DYNCREATE(CPageServices, CPropertyPage)
  21. CPageServices::CPageServices() : CPropertyPage(CPageServices::IDD)
  22. {
  23. //{{AFX_DATA_INIT(CPageServices)
  24. // NOTE: the ClassWizard will add member initialization here
  25. //}}AFX_DATA_INIT
  26. m_fFillingList = FALSE;
  27. m_pBuffer = NULL;
  28. m_dwSize = 0;
  29. m_fHideMicrosoft = FALSE;
  30. m_fShowWarning = TRUE;
  31. }
  32. CPageServices::~CPageServices()
  33. {
  34. if (m_pBuffer)
  35. delete [] m_pBuffer;
  36. }
  37. void CPageServices::DoDataExchange(CDataExchange* pDX)
  38. {
  39. CPropertyPage::DoDataExchange(pDX);
  40. //{{AFX_DATA_MAP(CPageServices)
  41. // NOTE: the ClassWizard will add DDX and DDV calls here
  42. //}}AFX_DATA_MAP
  43. }
  44. BEGIN_MESSAGE_MAP(CPageServices, CPropertyPage)
  45. //{{AFX_MSG_MAP(CPageServices)
  46. ON_WM_DESTROY()
  47. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LISTSERVICES, OnItemChangedListServices)
  48. ON_BN_CLICKED(IDC_BUTTONSERVDISABLEALL, OnButtonDisableAll)
  49. ON_BN_CLICKED(IDC_BUTTONSERVENABLEALL, OnButtonEnableAll)
  50. ON_BN_CLICKED(IDC_CHECKHIDEMS, OnCheckHideMS)
  51. ON_NOTIFY(LVN_COLUMNCLICK, IDC_LISTSERVICES, OnColumnClickListServices)
  52. ON_NOTIFY(NM_SETFOCUS, IDC_LISTSERVICES, OnSetFocusList)
  53. //}}AFX_MSG_MAP
  54. END_MESSAGE_MAP()
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CPageServices message handlers
  57. BOOL CPageServices::OnInitDialog()
  58. {
  59. CPropertyPage::OnInitDialog();
  60. // Attach a CWindow to the list and set it up to have check boxes.
  61. m_list.Attach(GetDlgItem(IDC_LISTSERVICES)->m_hWnd);
  62. ListView_SetExtendedListViewStyle(m_list.m_hWnd, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
  63. // Insert all of the columns in the list.
  64. struct { UINT m_uiStringResource; int m_iPercentOfWidth; } aColumns[] =
  65. {
  66. { IDS_STATUS_COLUMN, 12 },
  67. { IDS_MANUFACTURER_COLUMN, 44 },
  68. { IDS_REQUIREDSERVICE, 12 },
  69. { IDS_SERVICE_COLUMN, 30 },
  70. { 0, 0 }
  71. };
  72. CRect rect;
  73. m_list.GetClientRect(&rect);
  74. int cxWidth = rect.Width();
  75. LVCOLUMN lvc;
  76. lvc.mask = LVCF_TEXT | LVCF_WIDTH;
  77. CString strCaption;
  78. m_fFillingList = TRUE;
  79. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  80. for (int i = 0; aColumns[i].m_uiStringResource; i++)
  81. {
  82. strCaption.LoadString(aColumns[i].m_uiStringResource);
  83. lvc.pszText = (LPTSTR)(LPCTSTR)strCaption;
  84. lvc.cx = aColumns[i].m_iPercentOfWidth * cxWidth / 100;
  85. ListView_InsertColumn(m_list.m_hWnd, 0, &lvc);
  86. }
  87. LoadServiceList();
  88. SetCheckboxesFromRegistry();
  89. m_fFillingList = FALSE;
  90. CheckDlgButton(IDC_CHECKHIDEMS, (m_fHideMicrosoft) ? BST_CHECKED : BST_UNCHECKED);
  91. DWORD dwValue;
  92. CRegKey regkey;
  93. regkey.Attach(GetRegKey());
  94. m_fShowWarning = (ERROR_SUCCESS != regkey.QueryValue(dwValue, HIDEWARNINGVALUE));
  95. m_iLastColumnSort = -1;
  96. SetControlState();
  97. m_fInitialized = TRUE;
  98. return TRUE; // return TRUE unless you set the focus to a control
  99. }
  100. void CPageServices::OnDestroy()
  101. {
  102. CPropertyPage::OnDestroy();
  103. EmptyServiceList(FALSE);
  104. }
  105. //-------------------------------------------------------------------------
  106. // Load the list of services into the list view.
  107. //-------------------------------------------------------------------------
  108. void CPageServices::LoadServiceList()
  109. {
  110. SC_HANDLE sch = ::OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
  111. if (sch == NULL)
  112. return;
  113. DWORD dwSize = 0, dwBytesNeeded, dwServicesReturned, dwResume = 0;
  114. LVITEM lvi;
  115. // Might want SERVICE_DRIVER | SERVICE_WIN32
  116. if (!EnumServicesStatus(sch, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, dwSize, &dwBytesNeeded, &dwServicesReturned, &dwResume))
  117. {
  118. if (::GetLastError() == ERROR_MORE_DATA)
  119. {
  120. dwSize = dwBytesNeeded;
  121. dwResume = 0;
  122. LPBYTE lpBuffer = new BYTE[dwSize];
  123. if (lpBuffer != NULL && EnumServicesStatus(sch, SERVICE_WIN32, SERVICE_STATE_ALL, (LPENUM_SERVICE_STATUS)lpBuffer, dwSize, &dwBytesNeeded, &dwServicesReturned, &dwResume))
  124. {
  125. LPENUM_SERVICE_STATUS pServices = (LPENUM_SERVICE_STATUS) lpBuffer;
  126. CString strStopped, strStartPending, strStopPending, strRunning, strContinuePending, strPausePending, strPaused;
  127. CString strYes;
  128. LPTSTR szEmpty = _T("");
  129. strStopped.LoadString(IDS_SERVICESTOPPED);
  130. strStartPending.LoadString(IDS_SERVICESTARTPENDING);
  131. strStopPending.LoadString(IDS_SERVICESTOPPENDING);
  132. strRunning.LoadString(IDS_SERVICERUNNING);
  133. strContinuePending.LoadString(IDS_SERVICECONTINUEPENDING);
  134. strPausePending.LoadString(IDS_SERVICEPAUSEPENDING);
  135. strPaused.LoadString(IDS_SERVICEPAUSED);
  136. strYes.LoadString(IDS_YES);
  137. CRegKey regkey;
  138. regkey.Attach(GetRegKey(GetName()));
  139. int iPosition = 0;
  140. for (DWORD dwIndex = 0; dwIndex < dwServicesReturned; dwIndex++)
  141. {
  142. // We want to skip any services that are already disabled, unless
  143. // that service was disabled by us. If it was disabled by us, then
  144. // it will be in the registry.
  145. DWORD dwStartType;
  146. CString strPath;
  147. SC_HANDLE schService = ::OpenService(sch, pServices->lpServiceName, SERVICE_QUERY_CONFIG);
  148. if (schService == NULL)
  149. {
  150. pServices++;
  151. continue;
  152. }
  153. if (!GetServiceInfo(schService, dwStartType, strPath))
  154. {
  155. ::CloseServiceHandle(schService);
  156. pServices++;
  157. continue;
  158. }
  159. ::CloseServiceHandle(schService);
  160. if (dwStartType == SERVICE_DISABLED)
  161. if (ERROR_SUCCESS != regkey.QueryValue(dwStartType, pServices->lpServiceName))
  162. {
  163. pServices++;
  164. continue;
  165. }
  166. // If we are hiding Microsoft services, check the manufacturer.
  167. CString strManufacturer;
  168. GetManufacturer(strPath, strManufacturer);
  169. if (m_fHideMicrosoft)
  170. {
  171. CString strSearch(strManufacturer);
  172. strSearch.MakeLower();
  173. if (strSearch.Find(_T("microsoft")) != -1)
  174. {
  175. pServices++;
  176. continue;
  177. }
  178. }
  179. // Insert the three columns.
  180. CServiceInfo * pServiceInfo = new CServiceInfo(pServices->lpServiceName, FALSE, dwStartType, strManufacturer, pServices->lpDisplayName);
  181. lvi.pszText = pServices->lpDisplayName;
  182. lvi.iSubItem = 0;
  183. lvi.iItem = iPosition++;
  184. lvi.lParam = (LPARAM) pServiceInfo;
  185. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  186. ListView_InsertItem(m_list.m_hWnd, &lvi);
  187. lvi.mask = LVIF_TEXT;
  188. lvi.pszText = IsServiceEssential((CServiceInfo *)lvi.lParam) ? ((LPTSTR)(LPCTSTR)strYes) : szEmpty;
  189. lvi.iSubItem = 1;
  190. pServiceInfo->m_strEssential = lvi.pszText;
  191. ListView_SetItem(m_list.m_hWnd, &lvi);
  192. lvi.pszText = (LPTSTR)(LPCTSTR)strManufacturer;
  193. lvi.iSubItem = 2;
  194. ListView_SetItem(m_list.m_hWnd, &lvi);
  195. switch (pServices->ServiceStatus.dwCurrentState)
  196. {
  197. case SERVICE_STOPPED:
  198. lvi.pszText = (LPTSTR)(LPCTSTR)strStopped; break;
  199. case SERVICE_START_PENDING:
  200. lvi.pszText = (LPTSTR)(LPCTSTR)strStartPending; break;
  201. case SERVICE_STOP_PENDING:
  202. lvi.pszText = (LPTSTR)(LPCTSTR)strStopPending; break;
  203. case SERVICE_RUNNING:
  204. lvi.pszText = (LPTSTR)(LPCTSTR)strRunning; break;
  205. case SERVICE_CONTINUE_PENDING:
  206. lvi.pszText = (LPTSTR)(LPCTSTR)strContinuePending; break;
  207. case SERVICE_PAUSE_PENDING:
  208. lvi.pszText = (LPTSTR)(LPCTSTR)strPausePending; break;
  209. case SERVICE_PAUSED:
  210. lvi.pszText = (LPTSTR)(LPCTSTR)strPaused; break;
  211. }
  212. lvi.iSubItem = 3;
  213. pServiceInfo->m_strStatus = lvi.pszText;
  214. ListView_SetItem(m_list.m_hWnd, &lvi);
  215. pServices++;
  216. }
  217. }
  218. delete [] lpBuffer;
  219. }
  220. }
  221. ::CloseServiceHandle(sch);
  222. }
  223. //-------------------------------------------------------------------------
  224. // Empty the list of services.
  225. //-------------------------------------------------------------------------
  226. void CPageServices::EmptyServiceList(BOOL fUpdateUI)
  227. {
  228. LVITEM lvi;
  229. lvi.mask = LVIF_PARAM;
  230. lvi.iSubItem = 0;
  231. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  232. {
  233. lvi.iItem = i;
  234. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  235. {
  236. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  237. if (pService)
  238. delete pService;
  239. }
  240. }
  241. if (fUpdateUI)
  242. ListView_DeleteAllItems(m_list.m_hWnd);
  243. }
  244. //-------------------------------------------------------------------------
  245. // Sets the check boxes in the list view to the state stored in the
  246. // registry (which contains a list of what we've disabled).
  247. //-------------------------------------------------------------------------
  248. void CPageServices::SetCheckboxesFromRegistry()
  249. {
  250. CRegKey regkey;
  251. regkey.Attach(GetRegKey(GetName()));
  252. LVITEM lvi;
  253. lvi.mask = LVIF_PARAM;
  254. lvi.iSubItem = 0;
  255. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  256. {
  257. lvi.iItem = i;
  258. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  259. {
  260. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  261. if (pService)
  262. {
  263. if (ERROR_SUCCESS == regkey.QueryValue(pService->m_dwOldState, (LPCTSTR)pService->m_strService))
  264. {
  265. ListView_SetCheckState(m_list.m_hWnd, i, FALSE);
  266. pService->m_fChecked = FALSE;
  267. }
  268. else
  269. {
  270. ListView_SetCheckState(m_list.m_hWnd, i, TRUE);
  271. pService->m_fChecked = TRUE;
  272. }
  273. }
  274. }
  275. }
  276. }
  277. //-------------------------------------------------------------------------
  278. // Sets the registry list of disabled services from the checkboxes in the
  279. // list. If fCommit is true, it means that we are applying the changes
  280. // permanently. Remove all the registry entries which would allow us
  281. // to undo a change.
  282. //-------------------------------------------------------------------------
  283. void CPageServices::SetRegistryFromCheckboxes(BOOL fCommit)
  284. {
  285. CRegKey regkey;
  286. regkey.Attach(GetRegKey(GetName()));
  287. if ((HKEY)regkey != NULL)
  288. {
  289. LVITEM lvi;
  290. lvi.mask = LVIF_PARAM;
  291. lvi.iSubItem = 0;
  292. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  293. {
  294. lvi.iItem = i;
  295. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  296. {
  297. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  298. if (pService)
  299. {
  300. if (!pService->m_fChecked && !fCommit)
  301. regkey.SetValue(pService->m_dwOldState, (LPCTSTR)pService->m_strService);
  302. else
  303. regkey.DeleteValue((LPCTSTR)pService->m_strService);
  304. }
  305. }
  306. }
  307. }
  308. }
  309. //-------------------------------------------------------------------------
  310. // Set the state for all of the services. Note - if the new state is false
  311. // (disabled) don't set the state for necessary services).
  312. //-------------------------------------------------------------------------
  313. void CPageServices::SetStateAll(BOOL fNewState)
  314. {
  315. m_fFillingList = TRUE;
  316. LVITEM lvi;
  317. lvi.mask = LVIF_PARAM;
  318. lvi.iSubItem = 0;
  319. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  320. {
  321. lvi.iItem = i;
  322. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  323. {
  324. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  325. if (pService && !IsServiceEssential(pService))
  326. {
  327. pService->m_fChecked = fNewState;
  328. ListView_SetCheckState(m_list.m_hWnd, i, fNewState);
  329. }
  330. }
  331. }
  332. m_fFillingList = FALSE;
  333. SetControlState();
  334. }
  335. //-------------------------------------------------------------------------
  336. // Set the state of the services to disabled or enabled based on the
  337. // values of the checkboxes.
  338. //-------------------------------------------------------------------------
  339. BOOL CPageServices::SetServiceStateFromCheckboxes()
  340. {
  341. DWORD dwError = 0;
  342. SC_HANDLE schManager =::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  343. if (schManager != NULL)
  344. {
  345. LVITEM lvi;
  346. lvi.mask = LVIF_PARAM;
  347. lvi.iSubItem = 0;
  348. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  349. {
  350. lvi.iItem = i;
  351. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  352. {
  353. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  354. if (pService)
  355. {
  356. // Open this service and get the current state.
  357. SC_HANDLE schService = ::OpenService(schManager, pService->m_strService, SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG);
  358. if (schService != NULL)
  359. {
  360. DWORD dwStart;
  361. CString strPath;
  362. if (GetServiceInfo(schService, dwStart, strPath))
  363. {
  364. DWORD dwNewStart = 0;
  365. if (dwStart != SERVICE_DISABLED && !pService->m_fChecked)
  366. {
  367. pService->m_dwOldState = dwStart;
  368. if (!::ChangeServiceConfig(schService, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
  369. dwError = ::GetLastError();
  370. }
  371. else if (dwStart == SERVICE_DISABLED && pService->m_fChecked)
  372. {
  373. if (!::ChangeServiceConfig(schService, SERVICE_NO_CHANGE, pService->m_dwOldState, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
  374. dwError = ::GetLastError();
  375. }
  376. }
  377. ::CloseServiceHandle(schService);
  378. }
  379. else
  380. dwError = ::GetLastError();
  381. }
  382. }
  383. }
  384. ::CloseServiceHandle(schManager);
  385. }
  386. else
  387. dwError = ::GetLastError();
  388. if (dwError != 0)
  389. Message((dwError == ERROR_ACCESS_DENIED) ? IDS_SERVICEACCESSDENIED : IDS_SERVICEOTHERERROR);
  390. return (dwError == 0);
  391. }
  392. //-------------------------------------------------------------------------
  393. // Get the start type for the specified service. This will use a member
  394. // variable buffer and size (so this won't need to allocate a new buffer
  395. // each time).
  396. //
  397. // This will also get the path for the service.
  398. //-------------------------------------------------------------------------
  399. BOOL CPageServices::GetServiceInfo(SC_HANDLE schService, DWORD & dwStartType, CString & strPath)
  400. {
  401. DWORD dwSizeNeeded;
  402. if (!::QueryServiceConfig(schService, (LPQUERY_SERVICE_CONFIG)m_pBuffer, m_dwSize, &dwSizeNeeded))
  403. {
  404. if (ERROR_INSUFFICIENT_BUFFER != ::GetLastError())
  405. return FALSE;
  406. if (m_pBuffer)
  407. delete [] m_pBuffer;
  408. m_pBuffer = new BYTE[dwSizeNeeded];
  409. m_dwSize = dwSizeNeeded;
  410. if (!::QueryServiceConfig(schService, (LPQUERY_SERVICE_CONFIG)m_pBuffer, m_dwSize, &dwSizeNeeded))
  411. return FALSE;
  412. }
  413. dwStartType = ((LPQUERY_SERVICE_CONFIG)m_pBuffer)->dwStartType;
  414. strPath = ((LPQUERY_SERVICE_CONFIG)m_pBuffer)->lpBinaryPathName;
  415. return TRUE;
  416. }
  417. //-------------------------------------------------------------------------
  418. // Get the manufacturer for the named file.
  419. //-------------------------------------------------------------------------
  420. void CPageServices::GetManufacturer(LPCTSTR szFilename, CString & strManufacturer)
  421. {
  422. // Trim off any command line stuff extraneous to the path.
  423. CString strPath(szFilename);
  424. int iEnd = strPath.Find(_T('.'));
  425. if (iEnd == -1)
  426. iEnd = strPath.ReverseFind(_T('\\'));
  427. if (iEnd != -1)
  428. {
  429. int iSpace = strPath.Find(_T(' '), iEnd);
  430. if (iSpace != -1)
  431. strPath = strPath.Left(iSpace + 1);
  432. }
  433. strPath.TrimRight();
  434. // If there is no extension, then we'll try looking for a file with
  435. // an "EXE" extension.
  436. iEnd = strPath.Find(_T('.'));
  437. if (iEnd == -1)
  438. strPath += _T(".exe");
  439. strManufacturer.Empty();
  440. if (SUCCEEDED(m_fileversion.QueryFile((LPCTSTR)strPath)))
  441. strManufacturer = m_fileversion.GetCompany();
  442. if (strManufacturer.IsEmpty())
  443. strManufacturer.LoadString(IDS_UNKNOWN);
  444. }
  445. //-------------------------------------------------------------------------
  446. // Save the state of each of the services by maintaining a list of services
  447. // we've checked as disabled.
  448. //-------------------------------------------------------------------------
  449. void CPageServices::SaveServiceState()
  450. {
  451. LVITEM lvi;
  452. lvi.mask = LVIF_PARAM;
  453. lvi.iSubItem = 0;
  454. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  455. {
  456. lvi.iItem = i;
  457. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  458. {
  459. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  460. if (pService)
  461. {
  462. POSITION p = m_listDisabled.Find(pService->m_strService);
  463. if (pService->m_fChecked && p != NULL)
  464. m_listDisabled.RemoveAt(p);
  465. else if (!pService->m_fChecked && p == NULL)
  466. m_listDisabled.AddHead(pService->m_strService);
  467. }
  468. }
  469. }
  470. }
  471. //-------------------------------------------------------------------------
  472. // Restore the checked state of the list based on the contents of the list
  473. // of disabled services.
  474. //-------------------------------------------------------------------------
  475. void CPageServices::RestoreServiceState()
  476. {
  477. LVITEM lvi;
  478. lvi.mask = LVIF_PARAM;
  479. lvi.iSubItem = 0;
  480. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  481. {
  482. lvi.iItem = i;
  483. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  484. {
  485. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  486. if (pService)
  487. {
  488. pService->m_fChecked = (m_listDisabled.Find(pService->m_strService) == NULL);
  489. ListView_SetCheckState(m_list.m_hWnd, i, pService->m_fChecked);
  490. }
  491. }
  492. }
  493. }
  494. //-------------------------------------------------------------------------
  495. // Indicate if the service is essential (i.e. it shouldn't be disabled).
  496. //-------------------------------------------------------------------------
  497. BOOL CPageServices::IsServiceEssential(CServiceInfo * pService)
  498. {
  499. ASSERT(pService);
  500. CString strService(pService->m_strService);
  501. strService.MakeLower();
  502. for (int i = 0; aszEssentialServices[i] != NULL; i++)
  503. if (strService.Find(aszEssentialServices[i]) != -1)
  504. return TRUE;
  505. return FALSE;
  506. }
  507. // A function for sorting the service list. The low byte of lParamSort is the column
  508. // to sort by. The next higher byte indicates whether the sort should be reversed.
  509. int CALLBACK ServiceListSortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  510. {
  511. int iReturn = 0;
  512. int iColumn = (int)lParamSort & 0x00FF;
  513. int iReverse = (int)lParamSort & 0xFF00;
  514. CPageServices::CServiceInfo * pService1 = (CPageServices::CServiceInfo *)lParam1;
  515. CPageServices::CServiceInfo * pService2 = (CPageServices::CServiceInfo *)lParam2;
  516. if (pService1 && pService2)
  517. {
  518. CString str1, str2;
  519. switch (iColumn)
  520. {
  521. case 0:
  522. str1 = pService1->m_strDisplay;
  523. str2 = pService2->m_strDisplay;
  524. break;
  525. case 1:
  526. str1 = pService1->m_strEssential;
  527. str2 = pService2->m_strEssential;
  528. break;
  529. case 2:
  530. str1 = pService1->m_strManufacturer;
  531. str2 = pService2->m_strManufacturer;
  532. break;
  533. case 3:
  534. str1 = pService1->m_strStatus;
  535. str2 = pService2->m_strStatus;
  536. break;
  537. default:
  538. break;
  539. }
  540. iReturn = str1.Collate(str2);
  541. }
  542. if (iReverse)
  543. iReturn *= -1;
  544. return iReturn;
  545. }
  546. //-------------------------------------------------------------------------
  547. // If there is a change to the list, check to see if the user has changed
  548. // the state of a check box.
  549. //-------------------------------------------------------------------------
  550. void CPageServices::OnItemChangedListServices(NMHDR * pNMHDR, LRESULT * pResult)
  551. {
  552. NM_LISTVIEW * pnmv = (NM_LISTVIEW *)pNMHDR;
  553. if (m_fFillingList)
  554. {
  555. *pResult = 0;
  556. return;
  557. }
  558. if (!pnmv)
  559. {
  560. *pResult = 0;
  561. return;
  562. }
  563. LVITEM lvi;
  564. lvi.mask = LVIF_PARAM;
  565. lvi.iSubItem = 0;
  566. lvi.iItem = pnmv->iItem;
  567. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  568. {
  569. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  570. if (pService)
  571. {
  572. if (pService->m_fChecked != (BOOL)ListView_GetCheckState(m_list.m_hWnd, pnmv->iItem))
  573. {
  574. if (IsServiceEssential(pService))
  575. {
  576. m_fFillingList = TRUE;
  577. ListView_SetCheckState(m_list.m_hWnd, pnmv->iItem, TRUE);
  578. m_fFillingList = FALSE;
  579. if (m_fShowWarning)
  580. {
  581. CEssentialServiceDialog dlg;
  582. dlg.DoModal();
  583. if (dlg.m_fDontShow)
  584. {
  585. m_fShowWarning = FALSE;
  586. CRegKey regkey;
  587. regkey.Attach(GetRegKey());
  588. regkey.SetValue(1, HIDEWARNINGVALUE);
  589. }
  590. }
  591. *pResult = 0;
  592. return;
  593. }
  594. pService->m_fChecked = ListView_GetCheckState(m_list.m_hWnd, pnmv->iItem);
  595. SetModified(TRUE);
  596. SetControlState();
  597. }
  598. }
  599. }
  600. *pResult = 0;
  601. }
  602. //-------------------------------------------------------------------------
  603. // The user wants to enable or disable all the services.
  604. //-------------------------------------------------------------------------
  605. void CPageServices::OnButtonDisableAll()
  606. {
  607. SetStateAll(FALSE);
  608. SetModified(TRUE);
  609. }
  610. void CPageServices::OnButtonEnableAll()
  611. {
  612. SetStateAll(TRUE);
  613. SetModified(TRUE);
  614. }
  615. //-------------------------------------------------------------------------
  616. // If the user clicks the "Hide Microsoft Services" check box, refill the
  617. // list of services appropriately.
  618. //-------------------------------------------------------------------------
  619. void CPageServices::OnCheckHideMS()
  620. {
  621. m_fHideMicrosoft = (IsDlgButtonChecked(IDC_CHECKHIDEMS) == BST_CHECKED);
  622. m_fFillingList = TRUE;
  623. SaveServiceState();
  624. EmptyServiceList();
  625. LoadServiceList();
  626. RestoreServiceState();
  627. m_fFillingList = FALSE;
  628. SetControlState();
  629. }
  630. //-------------------------------------------------------------------------
  631. // If the user clicks on a column, we need to sort by that field. The
  632. // low byte of the LPARAM we pass is the column to sort by, the next byte
  633. // indicates if the sort should be reversed.
  634. //-------------------------------------------------------------------------
  635. void CPageServices::OnColumnClickListServices(NMHDR * pNMHDR, LRESULT * pResult)
  636. {
  637. LPNMLISTVIEW pnmv = (LPNMLISTVIEW) pNMHDR;
  638. if (pnmv)
  639. {
  640. if (m_iLastColumnSort == pnmv->iSubItem)
  641. m_iSortReverse ^= 1;
  642. else
  643. {
  644. m_iSortReverse = 0;
  645. m_iLastColumnSort = pnmv->iSubItem;
  646. }
  647. LPARAM lparam = (LPARAM)((m_iSortReverse << 8) | pnmv->iSubItem);
  648. ListView_SortItems(m_list.m_hWnd, (PFNLVCOMPARE) ServiceListSortFunc, lparam);
  649. }
  650. *pResult = 0;
  651. }
  652. //-------------------------------------------------------------------------
  653. // Return the current state of the tab (need to look through the list).
  654. //-------------------------------------------------------------------------
  655. CPageBase::TabState CPageServices::GetCurrentTabState()
  656. {
  657. if (!m_fInitialized)
  658. return GetAppliedTabState();
  659. TabState stateReturn = USER;
  660. BOOL fAllEnabled = TRUE, fAllDisabled = TRUE;
  661. LVITEM lvi;
  662. lvi.mask = LVIF_PARAM;
  663. lvi.iSubItem = 0;
  664. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  665. {
  666. lvi.iItem = i;
  667. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  668. {
  669. CServiceInfo * pService = (CServiceInfo *)lvi.lParam;
  670. if (pService && !IsServiceEssential(pService))
  671. {
  672. if (pService->m_fChecked)
  673. fAllDisabled = FALSE;
  674. else
  675. fAllEnabled = FALSE;
  676. }
  677. }
  678. }
  679. if (fAllEnabled)
  680. stateReturn = NORMAL;
  681. else if (fAllDisabled)
  682. stateReturn = DIAGNOSTIC;
  683. return stateReturn;
  684. }
  685. //-------------------------------------------------------------------------
  686. // Applying the changes for the services tab means setting the service
  687. // states from the checkboxes, and saving the checkbox values in the
  688. // registry.
  689. //
  690. // Finally, the base class implementation is called to maintain the
  691. // applied tab state.
  692. //-------------------------------------------------------------------------
  693. BOOL CPageServices::OnApply()
  694. {
  695. SetServiceStateFromCheckboxes();
  696. SetRegistryFromCheckboxes();
  697. CPageBase::SetAppliedState(GetCurrentTabState());
  698. // CancelToClose();
  699. m_fMadeChange = TRUE;
  700. return TRUE;
  701. }
  702. //-------------------------------------------------------------------------
  703. // Committing the changes means applying changes, then saving the current
  704. // values to the registry with the commit flag. Refill the list.
  705. //
  706. // Then call the base class implementation.
  707. //-------------------------------------------------------------------------
  708. void CPageServices::CommitChanges()
  709. {
  710. OnApply();
  711. SetRegistryFromCheckboxes(TRUE);
  712. m_fFillingList = TRUE;
  713. EmptyServiceList();
  714. LoadServiceList();
  715. SetCheckboxesFromRegistry();
  716. m_fFillingList = FALSE;
  717. CPageBase::CommitChanges();
  718. }
  719. //-------------------------------------------------------------------------
  720. // Set the overall state of the tab to normal or diagnostic.
  721. //-------------------------------------------------------------------------
  722. void CPageServices::SetNormal()
  723. {
  724. SetStateAll(TRUE);
  725. }
  726. void CPageServices::SetDiagnostic()
  727. {
  728. SetStateAll(FALSE);
  729. }
  730. //-------------------------------------------------------------------------
  731. // If nothing is selected when the list gets focus, select the first item
  732. // (so the user sees where the focus is).
  733. //-------------------------------------------------------------------------
  734. void CPageServices::OnSetFocusList(NMHDR * pNMHDR, LRESULT * pResult)
  735. {
  736. if (0 == ListView_GetSelectedCount(m_list.m_hWnd) && 0 < ListView_GetItemCount(m_list.m_hWnd))
  737. ListView_SetItemState(m_list.m_hWnd, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  738. *pResult = 0;
  739. }
  740. //-------------------------------------------------------------------------
  741. // Update the state of the controls (the Enable and Disable All buttons).
  742. //-------------------------------------------------------------------------
  743. void CPageServices::SetControlState()
  744. {
  745. BOOL fAllEnabled = TRUE, fAllDisabled = TRUE;
  746. for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
  747. {
  748. BOOL fChecked = ListView_GetCheckState(m_list.m_hWnd, i);
  749. fAllDisabled = fAllDisabled && !fChecked;
  750. fAllEnabled = fAllEnabled && fChecked;
  751. }
  752. HWND hwndFocus = ::GetFocus();
  753. ::EnableWindow(GetDlgItemHWND(IDC_BUTTONSERVDISABLEALL), !fAllDisabled);
  754. if (fAllDisabled && hwndFocus == GetDlgItemHWND(IDC_BUTTONSERVDISABLEALL))
  755. PrevDlgCtrl();
  756. ::EnableWindow(GetDlgItemHWND(IDC_BUTTONSERVENABLEALL), !fAllEnabled);
  757. if (fAllEnabled && hwndFocus == GetDlgItemHWND(IDC_BUTTONSERVENABLEALL))
  758. NextDlgCtrl();
  759. }