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.

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