2 * PROJECT: ReactOS Applications
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: base/applications/msconfig_new/srvpage.cpp
5 * PURPOSE: Services page message handler
6 * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de>
7 * Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr>
14 #include "stringutils.h"
15 // #include "CmdLineParser.h"
17 #include "uxthemesupp.h"
21 // #include <atlbase.h>
25 static HWND hServicesPage
= NULL
;
26 static HWND hServicesListCtrl
= NULL
;
27 static int iSortedColumn
= 0;
28 static BOOL bMaskProprietarySvcs
= FALSE
;
30 DWORD
GetServicesActivation(VOID
)
33 RegGetDWORDValue(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\state", L
"services", &dwServices
);
37 BOOL
SetServicesActivation(DWORD dwState
)
39 return (RegSetDWORDValue(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\state", L
"services", TRUE
, dwState
) == ERROR_SUCCESS
);
43 RegisterNoMsgAnymore(VOID
)
45 return (RegSetDWORDValue(HKEY_CURRENT_USER
/* HKEY_LOCAL_MACHINE ?? */,
46 L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig",
47 L
"HideEssentialServiceWarning",
48 TRUE
, 1) == ERROR_SUCCESS
);
52 HideEssentialServiceWarning(VOID
)
57 bRetVal
= ( (RegGetDWORDValue(HKEY_CURRENT_USER
/* HKEY_LOCAL_MACHINE ?? */,
58 L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig",
59 L
"HideEssentialServiceWarning",
60 &dwValue
) == ERROR_SUCCESS
) &&
68 ServiceItem(const LPCWSTR lpszSvcName
,
71 m_lpszSvcName(lpszSvcName
),
72 m_bIsEnabled(bIsEnabled
),
73 m_bIsRequired(bIsRequired
)
79 CAtlStringW m_lpszSvcName
;
84 struct RegistryDisabledServiceItemParams
87 BOOL bIsKeyed
; // bIsKeyed == TRUE for a keyed-registered service ; == FALSE for a valued-registered service.
92 static CAtlList
<CAtlStringW
> userModificationsList
;
94 QUERY_REGISTRY_VALUES_ROUTINE(GetRegistryValuedDisabledServicesQueryRoutine
)
96 UNREFERENCED_PARAMETER(KeyName
);
97 UNREFERENCED_PARAMETER(ValueData
);
98 UNREFERENCED_PARAMETER(ValueLength
);
101 return ERROR_SUCCESS
;
103 RegistryDisabledServiceItemParams
* pContextParams
= (RegistryDisabledServiceItemParams
*)EntryContext
;
104 if (pContextParams
->bIsPresent
)
105 return ERROR_SUCCESS
;
107 if ( (hRootKey
== HKEY_LOCAL_MACHINE
) && (ValueType
== REG_DWORD
) && (ValueLength
== sizeof(DWORD
)) &&
108 (wcsicmp((LPCWSTR
)Context
, ValueName
) == 0) )
110 pContextParams
->bIsPresent
= TRUE
;
111 pContextParams
->bIsKeyed
= FALSE
;
112 pContextParams
->dwStartType
= *(DWORD
*)ValueData
;
113 // pContextParams->time = {};
117 pContextParams
->bIsPresent
= FALSE
;
118 pContextParams
->bIsKeyed
= FALSE
;
119 pContextParams
->dwStartType
= 0;
120 // pContextParams->time = {};
123 return ERROR_SUCCESS
;
126 QUERY_REGISTRY_KEYS_ROUTINE(GetRegistryKeyedDisabledServicesQueryRoutine
)
128 UNREFERENCED_PARAMETER(hRootKey
);
129 UNREFERENCED_PARAMETER(KeyName
);
132 return ERROR_SUCCESS
;
134 RegistryDisabledServiceItemParams
* pContextParams
= (RegistryDisabledServiceItemParams
*)EntryContext
;
135 if (pContextParams
->bIsPresent
)
136 return ERROR_SUCCESS
;
138 DWORD dwType
= 0, dwBufSize
= 0;
140 // Be careful, the order of the operations in the comparison is very important.
141 if ( (wcsicmp((LPCWSTR
)Context
, SubKeyName
) == 0) &&
142 (RegQueryValueEx(hOpenedSubKey
, /* ValueName == */ SubKeyName
, NULL
, &dwType
, NULL
, &dwBufSize
) == ERROR_SUCCESS
) &&
143 (dwType
== REG_DWORD
) && (dwBufSize
== sizeof(DWORD
)) )
146 SYSTEMTIME disableDate
= {};
150 RegGetDWORDValue(hOpenedSubKey
, NULL
, L
"DAY", &dwRegData
);
151 disableDate
.wDay
= LOWORD(dwRegData
);
154 RegGetDWORDValue(hOpenedSubKey
, NULL
, L
"HOUR", &dwRegData
);
155 disableDate
.wHour
= LOWORD(dwRegData
);
158 RegGetDWORDValue(hOpenedSubKey
, NULL
, L
"MINUTE", &dwRegData
);
159 disableDate
.wMinute
= LOWORD(dwRegData
);
162 RegGetDWORDValue(hOpenedSubKey
, NULL
, L
"MONTH", &dwRegData
);
163 disableDate
.wMonth
= LOWORD(dwRegData
);
166 RegGetDWORDValue(hOpenedSubKey
, NULL
, L
"SECOND", &dwRegData
);
167 disableDate
.wSecond
= LOWORD(dwRegData
);
170 RegGetDWORDValue(hOpenedSubKey
, NULL
, L
"YEAR", &dwRegData
);
171 disableDate
.wYear
= LOWORD(dwRegData
);
174 DWORD dwStartType
= 0;
175 RegGetDWORDValue(hOpenedSubKey
, NULL
, SubKeyName
/* Service name */, &dwStartType
);
177 pContextParams
->bIsPresent
= TRUE
;
178 pContextParams
->bIsKeyed
= TRUE
;
179 pContextParams
->dwStartType
= dwStartType
;
180 pContextParams
->time
= disableDate
;
184 pContextParams
->bIsPresent
= FALSE
;
185 pContextParams
->bIsKeyed
= TRUE
;
186 pContextParams
->dwStartType
= 0;
187 // pContextParams->time = {};
190 return ERROR_SUCCESS
;
195 static void AddService(SC_HANDLE hSCManager
, LPENUM_SERVICE_STATUS_PROCESS Service
, BOOL bHideOSVendorServices
)
198 // Retrieve a handle to the service.
200 SC_HANDLE hService
= OpenServiceW(hSCManager
, Service
->lpServiceName
, SERVICE_QUERY_CONFIG
);
201 if (hService
== NULL
)
204 DWORD dwBytesNeeded
= 0;
205 QueryServiceConfigW(hService
, NULL
, 0, &dwBytesNeeded
);
206 // if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
208 LPQUERY_SERVICE_CONFIG lpServiceConfig
= (LPQUERY_SERVICE_CONFIG
)MemAlloc(0, dwBytesNeeded
);
209 if (!lpServiceConfig
)
211 CloseServiceHandle(hService
);
214 QueryServiceConfigW(hService
, lpServiceConfig
, dwBytesNeeded
, &dwBytesNeeded
);
217 // Get the service's vendor...
219 LPWSTR lpszVendor
= NULL
;
221 // Isolate only the executable path, without any arguments.
222 // TODO: Correct at the level of CmdLineToArgv the potential bug when lpszFilename == NULL.
223 #if 0 // Disabled until CmdLineToArgv is included
224 unsigned int argc
= 0;
226 CmdLineToArgv(lpServiceConfig
->lpBinaryPathName
, &argc
, &argv
, L
" \t");
227 if (argc
>= 1 && argv
[0])
228 lpszVendor
= GetExecutableVendor(argv
[0]);
230 // Hackish solution taken from the original srvpage.c.
231 // Will be removed after CmdLineToArgv is introduced.
232 WCHAR FileName
[MAX_PATH
];
233 memset(&FileName
, 0, sizeof(FileName
));
234 if (wcscspn(lpServiceConfig
->lpBinaryPathName
, L
"\""))
236 wcsncpy(FileName
, lpServiceConfig
->lpBinaryPathName
, wcscspn(lpServiceConfig
->lpBinaryPathName
, L
" ") );
240 wcscpy(FileName
, lpServiceConfig
->lpBinaryPathName
);
242 lpszVendor
= GetExecutableVendor(FileName
);
245 lpszVendor
= LoadResourceString(hInst
, IDS_UNKNOWN
);
251 // ...and display or not the Microsoft / ReactOS services.
252 BOOL bContinue
= TRUE
;
253 if (bHideOSVendorServices
)
255 if (FindSubStrI(lpszVendor
, bIsWindows
? IDS_MICROSOFT
: IDS_REACTOS
))
261 BOOL bIsServiceEnabled
= (lpServiceConfig
->dwStartType
!= SERVICE_DISABLED
);
262 BOOL bAddServiceToList
= FALSE
;
263 BOOL bIsModifiedService
= FALSE
;
264 RegistryDisabledServiceItemParams params
= {};
267 // Try to look into the user modifications list...
269 POSITION it
= userModificationsList
.Find(Service
->lpServiceName
);
272 bAddServiceToList
= TRUE
;
273 bIsModifiedService
= TRUE
;
277 // ...if not found, try to find if the disabled service is in the registry.
279 if (!bAddServiceToList
)
281 if (!bIsServiceEnabled
)
283 QUERY_REGISTRY_KEYS_TABLE KeysQueryTable
[2] = {};
284 KeysQueryTable
[0].QueryRoutine
= GetRegistryKeyedDisabledServicesQueryRoutine
;
285 KeysQueryTable
[0].EntryContext
= ¶ms
;
286 RegQueryRegistryKeys(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", KeysQueryTable
, Service
->lpServiceName
);
288 bAddServiceToList
= params
.bIsPresent
;
290 if (bIsWindows
&& bIsPreVistaOSVersion
&& !bAddServiceToList
)
292 QUERY_REGISTRY_VALUES_TABLE ValuesQueryTable
[2] = {};
293 ValuesQueryTable
[0].QueryRoutine
= GetRegistryValuedDisabledServicesQueryRoutine
;
294 ValuesQueryTable
[0].EntryContext
= ¶ms
;
295 RegQueryRegistryValues(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", ValuesQueryTable
, Service
->lpServiceName
);
297 bAddServiceToList
= params
.bIsPresent
;
302 bAddServiceToList
= TRUE
;
306 if (bAddServiceToList
)
309 // Check if service is required by the system.
311 BOOL bIsRequired
= FALSE
;
314 QueryServiceConfig2(hService
, SERVICE_CONFIG_FAILURE_ACTIONS
, NULL
, 0, &dwBytesNeeded
);
315 // if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
317 LPSERVICE_FAILURE_ACTIONS lpServiceFailureActions
= (LPSERVICE_FAILURE_ACTIONS
)MemAlloc(0, dwBytesNeeded
);
318 if (!lpServiceFailureActions
)
321 MemFree(lpServiceConfig
);
322 CloseServiceHandle(hService
);
326 QueryServiceConfig2(hService
, SERVICE_CONFIG_FAILURE_ACTIONS
, (LPBYTE
)lpServiceFailureActions
, dwBytesNeeded
, &dwBytesNeeded
);
328 // In Microsoft's MSConfig, things are done just like that!! (extracted string values from msconfig.exe)
329 if ( ( wcsicmp(Service
->lpServiceName
, L
"rpcss" ) == 0 ||
330 wcsicmp(Service
->lpServiceName
, L
"rpclocator") == 0 ||
331 wcsicmp(Service
->lpServiceName
, L
"dcomlaunch") == 0 ) ||
332 ( lpServiceFailureActions
&&
333 (lpServiceFailureActions
->cActions
>= 1) &&
334 (lpServiceFailureActions
->lpsaActions
[0].Type
== SC_ACTION_REBOOT
) ) ) // We add also this test, which corresponds to real life.
338 MemFree(lpServiceFailureActions
);
341 // Add the service into the list.
344 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
345 item
.pszText
= Service
->lpDisplayName
;
346 item
.lParam
= reinterpret_cast<LPARAM
>(new ServiceItem(Service
->lpServiceName
, bIsServiceEnabled
, bIsRequired
));
347 item
.iItem
= ListView_InsertItem(hServicesListCtrl
, &item
);
351 LPWSTR lpszYes
= LoadResourceString(hInst
, IDS_YES
);
352 ListView_SetItemText(hServicesListCtrl
, item
.iItem
, 1, lpszYes
);
356 ListView_SetItemText(hServicesListCtrl
, item
.iItem
, 2, lpszVendor
);
358 LPWSTR lpszStatus
= LoadResourceString(hInst
, ((Service
->ServiceStatusProcess
.dwCurrentState
== SERVICE_STOPPED
) ? IDS_SERVICES_STATUS_STOPPED
: IDS_SERVICES_STATUS_RUNNING
));
359 ListView_SetItemText(hServicesListCtrl
, item
.iItem
, 3, lpszStatus
);
362 if (!bIsServiceEnabled
)
364 LPWSTR lpszUnknown
= LoadResourceString(hInst
, IDS_UNKNOWN
);
366 LPWSTR lpszDisableDate
= FormatDateTime(¶ms
.time
);
367 ListView_SetItemText(hServicesListCtrl
, item
.iItem
, 4, (lpszDisableDate
? lpszDisableDate
: lpszUnknown
));
368 FreeDateTime(lpszDisableDate
);
370 MemFree(lpszUnknown
);
373 ListView_SetCheckState(hServicesListCtrl
, item
.iItem
, (!bIsModifiedService
? bIsServiceEnabled
: !bIsServiceEnabled
));
378 MemFree(lpServiceConfig
);
379 CloseServiceHandle(hService
);
384 static void ClearServicesList(void)
387 lvitem
.mask
= LVIF_PARAM
;
388 lvitem
.iItem
= -1; // From the beginning.
390 while ((lvitem
.iItem
= ListView_GetNextItem(hServicesListCtrl
, lvitem
.iItem
, LVNI_ALL
)) != -1)
392 ListView_GetItem(hServicesListCtrl
, &lvitem
);
394 delete reinterpret_cast<ServiceItem
*>(lvitem
.lParam
);
395 lvitem
.lParam
= NULL
;
397 ListView_DeleteAllItems(hServicesListCtrl
);
402 static void GetServices(BOOL bHideOSVendorServices
= FALSE
)
405 // First of all, clear the list.
410 // Now, we can list the services.
413 // Open the Service Control Manager.
414 SC_HANDLE hSCManager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
415 if (hSCManager
== NULL
)
418 // Enumerate all the Win32 services.
419 DWORD dwBytesNeeded
= 0;
420 DWORD dwNumServices
= 0;
421 // DWORD dwResumeHandle = 0;
422 EnumServicesStatusExW(hSCManager
, SC_ENUM_PROCESS_INFO
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &dwBytesNeeded
, &dwNumServices
, NULL
/* &dwResumeHandle */, NULL
);
423 // if (GetLastError() == ERROR_MORE_DATA)
425 LPENUM_SERVICE_STATUS_PROCESS lpServices
= (LPENUM_SERVICE_STATUS_PROCESS
)MemAlloc(0, dwBytesNeeded
);
428 CloseServiceHandle(hSCManager
);
431 EnumServicesStatusExW(hSCManager
, SC_ENUM_PROCESS_INFO
, SERVICE_WIN32
, SERVICE_STATE_ALL
, (LPBYTE
)lpServices
, dwBytesNeeded
, &dwBytesNeeded
, &dwNumServices
, NULL
/* &dwResumeHandle */, NULL
);
433 // Add them into the list.
434 for (DWORD i
= 0 ; i
< dwNumServices
; ++i
)
436 AddService(hSCManager
, lpServices
+ i
, bHideOSVendorServices
);
441 CloseServiceHandle(hSCManager
);
447 RequiredServicesDisablingDialogWndProc(HWND hDlg
,
452 UNREFERENCED_PARAMETER(lParam
);
458 /* Correctly display message strings */
460 size_t itemLength
= 0;
461 LPWSTR szItem
= NULL
, szNewItem
= NULL
;
463 szOSVendor
= (bIsWindows
? IDS_WINDOWS
: IDS_REACTOS
);
465 itemLength
= GetWindowTextLength(GetDlgItem(hDlg
, IDC_STATIC_REQSVCSDIS_INFO
)) + 1;
466 szItem
= (LPWSTR
)MemAlloc(0, itemLength
* sizeof(WCHAR
));
467 GetDlgItemText(hDlg
, IDC_STATIC_REQSVCSDIS_INFO
, szItem
, (int)itemLength
);
468 szNewItem
= FormatString(szItem
, szOSVendor
);
469 SetDlgItemText(hDlg
, IDC_STATIC_REQSVCSDIS_INFO
, szNewItem
);
478 switch (LOWORD(wParam
))
482 if (Button_GetCheck(GetDlgItem(hDlg
, IDC_CBX_REQSVCSDIS_NO_MSG_ANYMORE
)) == BST_CHECKED
)
483 RegisterNoMsgAnymore();
485 EndDialog(hDlg
, LOWORD(wParam
));
490 EndDialog(hDlg
, LOWORD(wParam
));
503 static BOOL
ValidateItem(int index
, BOOL bNewState
, BOOL bDisplayErrors
)
505 ServiceItem
* pSvcItem
= NULL
;
508 truc
.mask
= LVIF_PARAM
;
510 ListView_GetItem(hServicesListCtrl
, &truc
);
512 // The lParam member must be valid.
513 pSvcItem
= reinterpret_cast<ServiceItem
*>(truc
.lParam
);
518 // Allow modifications only if the service is not a required service for the system,
519 // or allow only the activation of a disabled required service.
521 BOOL bOldState
= !!(ListView_GetCheckState(hServicesListCtrl
, truc
.iItem
/* == index */) % 2);
523 if ( !pSvcItem
->m_bIsRequired
||
524 (pSvcItem
->m_bIsRequired
&& !pSvcItem
->m_bIsEnabled
&& bOldState
== FALSE
&& bNewState
== TRUE
) )
526 if (bOldState
== bNewState
)
529 ListView_SetCheckState(hServicesListCtrl
, index
, bNewState
);
531 if (pSvcItem
->m_bIsEnabled
) // Enabled service.
533 if (bNewState
== FALSE
) // To be deactivated.
535 userModificationsList
.AddTail(pSvcItem
->m_lpszSvcName
);
537 else if (bNewState
== TRUE
) // To be reactivated
539 POSITION it
= userModificationsList
.Find(pSvcItem
->m_lpszSvcName
);
542 userModificationsList
.RemoveAt(it
);
546 OutputDebugString(_T("(1) \"WTF: What The Fukhurmajalmahamadahaldeliya ?!\" (The Dictator, Sacha Baron Cohen)\n"));
550 else // Disabled service.
552 if (bNewState
== TRUE
) // To be activated.
554 userModificationsList
.AddTail(pSvcItem
->m_lpszSvcName
);
556 else if (bNewState
== FALSE
) // To be redeactivated
558 POSITION it
= userModificationsList
.Find(pSvcItem
->m_lpszSvcName
);
561 userModificationsList
.RemoveAt(it
);
565 OutputDebugString(_T("(2) \"WTF: What The Fukhurmajalmahamadahaldeliya ?!\" (The Dictator, Sacha Baron Cohen)\n"));
576 DialogBoxW(hInst
, MAKEINTRESOURCEW(IDD_REQUIRED_SERVICES_DISABLING_DIALOG
), hServicesPage
/* hMainWnd */, RequiredServicesDisablingDialogWndProc
);
585 UpdateBtnStates(HWND hDlg
)
587 // HWND hTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE);
590 // "Enable all" / "Disable all" buttons.
592 // UINT uRootCheckState = TreeView_GetRealSubtreeState(hTree, TVI_ROOT);
593 UINT uRootCheckState
= ListView_GetCheckState(hServicesListCtrl
, 0);
594 #define OP(a, b) ((a) == (b) ? (a) : 2)
595 int index
= 0; // -1 // From the beginning + 1.
596 while ((index
= ListView_GetNextItem(hServicesListCtrl
, index
, LVNI_ALL
)) != -1)
598 UINT temp
= ListView_GetCheckState(hServicesListCtrl
, index
);
599 uRootCheckState
= OP(uRootCheckState
, temp
);
602 if (uRootCheckState
== 0)
604 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_ACTIVATE
) , TRUE
);
605 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_DEACTIVATE
), FALSE
);
607 else if (uRootCheckState
== 1)
609 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_ACTIVATE
) , FALSE
);
610 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_DEACTIVATE
), TRUE
);
612 else if (uRootCheckState
== 2)
614 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_ACTIVATE
) , TRUE
);
615 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_DEACTIVATE
), TRUE
);
619 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_ACTIVATE
) , FALSE
);
620 EnableWindow(GetDlgItem(hDlg
, IDC_BTN_SERVICES_DEACTIVATE
), FALSE
);
629 ServicesPageWndProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
631 UNREFERENCED_PARAMETER(lParam
);
632 UNREFERENCED_PARAMETER(wParam
);
638 hServicesPage
= hDlg
;
639 hServicesListCtrl
= GetDlgItem(hServicesPage
, IDC_SERVICES_LIST
);
642 // Correctly display message strings.
644 LPCWSTR szOSVendor
= (bIsWindows
? IDS_MICROSOFT
: IDS_REACTOS
);
646 size_t itemLength
= 0;
647 LPWSTR szItem
= NULL
, szNewItem
= NULL
;
649 itemLength
= GetWindowTextLength(GetDlgItem(hServicesPage
, IDC_STATIC_SERVICES_WARNING
)) + 1;
650 szItem
= (LPWSTR
)MemAlloc(0, itemLength
* sizeof(WCHAR
));
651 GetDlgItemText(hServicesPage
, IDC_STATIC_SERVICES_WARNING
, szItem
, (int)itemLength
);
652 szNewItem
= FormatString(szItem
, szOSVendor
);
653 SetDlgItemText(hServicesPage
, IDC_STATIC_SERVICES_WARNING
, szNewItem
);
657 itemLength
= GetWindowTextLength(GetDlgItem(hServicesPage
, IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS
)) + 1;
658 szItem
= (LPWSTR
)MemAlloc(0, itemLength
* sizeof(WCHAR
));
659 GetDlgItemText(hServicesPage
, IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS
, szItem
, (int)itemLength
);
660 szNewItem
= FormatString(szItem
, szOSVendor
);
661 SetDlgItemText(hServicesPage
, IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS
, szNewItem
);
666 // Initialize the styles.
668 DWORD dwStyle
= ListView_GetExtendedListViewStyle(hServicesListCtrl
);
669 ListView_SetExtendedListViewStyle(hServicesListCtrl
, dwStyle
| LVS_EX_FULLROWSELECT
| LVS_EX_CHECKBOXES
);
670 SetWindowTheme(hServicesListCtrl
, L
"Explorer", NULL
);
673 // Initialize the application page's controls.
675 LVCOLUMN column
= {};
677 // First column : Service's name.
678 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
679 column
.pszText
= LoadResourceString(hInst
, IDS_SERVICES_COLUMN_SERVICE
);
681 ListView_InsertColumn(hServicesListCtrl
, 0, &column
);
682 MemFree(column
.pszText
);
684 // Second column : Whether the service is required or not.
685 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
686 column
.pszText
= LoadResourceString(hInst
, IDS_SERVICES_COLUMN_REQ
);
688 ListView_InsertColumn(hServicesListCtrl
, 1, &column
);
689 MemFree(column
.pszText
);
691 // Third column : Service's vendor.
692 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
693 column
.pszText
= LoadResourceString(hInst
, IDS_SERVICES_COLUMN_VENDOR
);
695 ListView_InsertColumn(hServicesListCtrl
, 2, &column
);
696 MemFree(column
.pszText
);
698 // Fourth column : Service's status.
699 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
700 column
.pszText
= LoadResourceString(hInst
, IDS_SERVICES_COLUMN_STATUS
);
702 ListView_InsertColumn(hServicesListCtrl
, 3, &column
);
703 MemFree(column
.pszText
);
705 // Fifth column : Service's disabled date.
706 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
707 column
.pszText
= LoadResourceString(hInst
, IDS_SERVICES_COLUMN_DATEDISABLED
);
709 ListView_InsertColumn(hServicesListCtrl
, 4, &column
);
710 MemFree(column
.pszText
);
713 // Populate and sort the list.
716 ListView_Sort(hServicesListCtrl
, 0);
717 UpdateBtnStates(hDlg
);
719 // Select the first item.
720 ListView_SetItemState(hServicesListCtrl
, 0, LVIS_SELECTED
, LVIS_SELECTED
);
728 userModificationsList
.RemoveAll();
734 switch (LOWORD(wParam
))
736 case IDC_BTN_SERVICES_ACTIVATE
:
738 BOOL bAreThereMods
= FALSE
;
740 int index
= -1; // From the beginning.
741 while ((index
= ListView_GetNextItem(hServicesListCtrl
, index
, LVNI_ALL
)) != -1)
743 bAreThereMods
= ValidateItem(index
, TRUE
, FALSE
) || bAreThereMods
; // The order is verrrrrry important !!!!
748 UpdateBtnStates(hDlg
);
749 PropSheet_Changed(GetParent(hServicesPage
), hServicesPage
);
755 case IDC_BTN_SERVICES_DEACTIVATE
:
757 BOOL bAreThereMods
= FALSE
;
759 int index
= -1; // From the beginning.
760 while ((index
= ListView_GetNextItem(hServicesListCtrl
, index
, LVNI_ALL
)) != -1)
762 bAreThereMods
= ValidateItem(index
, FALSE
, FALSE
) || bAreThereMods
; // The order is verrrrrry important !!!!
767 UpdateBtnStates(hDlg
);
768 PropSheet_Changed(GetParent(hServicesPage
), hServicesPage
);
774 case IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS
:
776 bMaskProprietarySvcs
= !bMaskProprietarySvcs
;
777 GetServices(bMaskProprietarySvcs
);
778 UpdateBtnStates(hDlg
);
789 case UM_CHECKSTATECHANGE
:
791 BOOL bNewCheckState
= !!((ListView_GetCheckState(hServicesListCtrl
, int(lParam
)) + 1) % 2);
793 if (ValidateItem(/*reinterpret_cast<int>*/ int(lParam
), bNewCheckState
, !HideEssentialServiceWarning()))
795 UpdateBtnStates(hDlg
);
796 PropSheet_Changed(GetParent(hServicesPage
), hServicesPage
);
804 if (reinterpret_cast<LPNMHDR
>(lParam
)->hwndFrom
== hServicesListCtrl
)
806 switch (reinterpret_cast<LPNMHDR
>(lParam
)->code
)
811 DWORD dwpos
= GetMessagePos();
812 LVHITTESTINFO ht
= {};
813 ht
.pt
.x
= GET_X_LPARAM(dwpos
);
814 ht
.pt
.y
= GET_Y_LPARAM(dwpos
);
815 MapWindowPoints(HWND_DESKTOP
/*NULL*/, hServicesListCtrl
, &ht
.pt
, 1);
818 * We use ListView_SubItemHitTest(...) and not ListView_HitTest(...)
819 * because ListView_HitTest(...) returns bad flags when one clicks
820 * on a sub-item different from 0. The flags then contain LVHT_ONITEMSTATEICON
821 * which must not be obviously present in this case.
823 ListView_SubItemHitTest(hServicesListCtrl
, &ht
);
825 if (LVHT_ONITEMSTATEICON
& ht
.flags
)
827 PostMessage(hDlg
, UM_CHECKSTATECHANGE
, 0, (LPARAM
)ht
.iItem
);
829 // Disable default behaviour. Needed for the UM_CHECKSTATECHANGE
830 // custom notification to work as expected.
831 SetWindowLongPtr(hDlg
, DWLP_MSGRESULT
, TRUE
);
840 // We deactivate double-clicks.
841 SetWindowLongPtr(hDlg
, DWLP_MSGRESULT
, TRUE
);
847 if (reinterpret_cast<LPNMLVKEYDOWN
>(lParam
)->wVKey
== VK_SPACE
)
849 int iItem
= ListView_GetSelectionMark(hServicesListCtrl
);
850 PostMessage(hDlg
, UM_CHECKSTATECHANGE
, 0, (LPARAM
)iItem
);
852 // Disable default behaviour. Needed for the UM_CHECKSTATECHANGE
853 // custom notification to work as expected.
854 SetWindowLongPtr(hDlg
, DWLP_MSGRESULT
, TRUE
);
860 case LVN_COLUMNCLICK
:
862 int iSortingColumn
= reinterpret_cast<LPNMLISTVIEW
>(lParam
)->iSubItem
;
864 ListView_SortEx(hServicesListCtrl
, iSortingColumn
, iSortedColumn
);
865 iSortedColumn
= iSortingColumn
;
873 switch (reinterpret_cast<LPNMHDR
>(lParam
)->code
)
877 // Try to apply the modifications to the system.
878 MessageBox(NULL
, _T("In Services page: PSN_APPLY"), _T("Info"), MB_ICONINFORMATION
);
884 int iRetVal = MessageBox(NULL, _T("Would you really want to modify the configuration of your system ?"), _T("Warning"), MB_ICONWARNING | MB_YESNOCANCEL);
886 if (iRetVal == IDYES /\* modifications are OK *\/)
887 SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_NOERROR);
888 else if (iRetVal == IDNO /\* modifications are not OK *\/)
889 SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_NOERROR);
890 else // if (iRetVal == IDCANCEL) // There was an error...
891 SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_INVALID);
895 // We modify the services which are stored in the user modification list.
898 // 1- Open the Service Control Manager for modifications.
899 SC_HANDLE hSCManager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
900 if (hSCManager
!= NULL
)
904 for (POSITION it
= userModificationsList
.GetHeadPosition(); it
; userModificationsList
.GetNext(it
))
906 svcName
= userModificationsList
.GetAt(it
);
908 // 2- Retrieve a handle to the service.
909 SC_HANDLE hService
= OpenServiceW(hSCManager
, svcName
, SERVICE_QUERY_CONFIG
| SERVICE_CHANGE_CONFIG
);
910 if (hService
== NULL
)
912 // TODO : Show a message box.
916 DWORD dwBytesNeeded
= 0;
917 QueryServiceConfigW(hService
, NULL
, 0, &dwBytesNeeded
);
918 // if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
920 LPQUERY_SERVICE_CONFIG lpServiceConfig
= (LPQUERY_SERVICE_CONFIG
)MemAlloc(0, dwBytesNeeded
);
921 if (!lpServiceConfig
)
923 CloseServiceHandle(hService
);
924 continue; // TODO ? Show a message box...
926 QueryServiceConfigW(hService
, lpServiceConfig
, dwBytesNeeded
, &dwBytesNeeded
);
928 if (lpServiceConfig
->dwStartType
== SERVICE_DISABLED
) // We have a disabled service which is becoming to be enabled.
930 // 3a- Retrieve the properties of the disabled service from the registry.
931 RegistryDisabledServiceItemParams params
= {};
933 QUERY_REGISTRY_KEYS_TABLE KeysQueryTable
[2] = {};
934 KeysQueryTable
[0].QueryRoutine
= GetRegistryKeyedDisabledServicesQueryRoutine
;
935 KeysQueryTable
[0].EntryContext
= ¶ms
;
936 RegQueryRegistryKeys(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", KeysQueryTable
, (PVOID
)svcName
);
938 if (bIsWindows
&& bIsPreVistaOSVersion
&& !params
.bIsPresent
)
940 QUERY_REGISTRY_VALUES_TABLE ValuesQueryTable
[2] = {};
941 ValuesQueryTable
[0].QueryRoutine
= GetRegistryValuedDisabledServicesQueryRoutine
;
942 ValuesQueryTable
[0].EntryContext
= ¶ms
;
943 RegQueryRegistryValues(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", ValuesQueryTable
, (PVOID
)svcName
);
946 if (params
.bIsPresent
)
948 // 4a- Modify the service.
949 ChangeServiceConfigW(hService
, SERVICE_NO_CHANGE
, params
.dwStartType
, SERVICE_NO_CHANGE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
951 // 5a- Remove the registry entry of the service.
954 CAtlStringW
serviceRegKey(L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services\\");
955 serviceRegKey
+= svcName
;
956 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, serviceRegKey
);
958 /***** HACK for Windows < Vista (e.g. 2000, Xp, 2003...) *****/
960 // Delete also the valued-entry of the service.
962 if (bIsWindows
&& bIsPreVistaOSVersion
)
965 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", 0, KEY_SET_VALUE
/*KEY_READ*/, &hSubKey
) == ERROR_SUCCESS
)
967 RegDeleteValue(hSubKey
, svcName
);
968 RegCloseKey(hSubKey
);
971 /*************************************************************/
976 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", 0, KEY_SET_VALUE
/*KEY_READ*/, &hSubKey
) == ERROR_SUCCESS
)
978 RegDeleteValue(hSubKey
, svcName
);
979 RegCloseKey(hSubKey
);
983 ////////// HACKHACKHACKHACKHACKHACKHACKHACKHACKHACKHACK ///////////
984 // userModificationsList.RemoveAt(it);
988 // Ohoh !! We have a very big problem.
989 MessageBox(NULL
, _T("WTF ??"), _T("FATAL ERROR !!!!"), MB_ICONERROR
);
992 else // We have an enabled service which is becoming to be disabled.
994 // 3b- Retrieve the local time of disabling.
995 SYSTEMTIME disableDate
= {};
996 GetLocalTime(&disableDate
);
998 // 4b- Modify the service.
999 ChangeServiceConfigW(hService
, SERVICE_NO_CHANGE
, SERVICE_DISABLED
, SERVICE_NO_CHANGE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1001 // 5b- Register the service into the registry.
1002 CAtlStringW
serviceRegKey(L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services\\");
1003 serviceRegKey
+= svcName
;
1004 HKEY hSubKey
= NULL
;
1005 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
, serviceRegKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hSubKey
, NULL
) == ERROR_SUCCESS
)
1007 RegSetDWORDValue(hSubKey
, NULL
, svcName
, FALSE
, lpServiceConfig
->dwStartType
);
1009 #if 1 // DisableDate
1010 RegSetDWORDValue(hSubKey
, NULL
, L
"DAY" , FALSE
, disableDate
.wDay
);
1011 RegSetDWORDValue(hSubKey
, NULL
, L
"HOUR" , FALSE
, disableDate
.wHour
);
1012 RegSetDWORDValue(hSubKey
, NULL
, L
"MINUTE", FALSE
, disableDate
.wMinute
);
1013 RegSetDWORDValue(hSubKey
, NULL
, L
"MONTH" , FALSE
, disableDate
.wMonth
);
1014 RegSetDWORDValue(hSubKey
, NULL
, L
"SECOND", FALSE
, disableDate
.wSecond
);
1015 RegSetDWORDValue(hSubKey
, NULL
, L
"YEAR" , FALSE
, disableDate
.wYear
);
1018 RegCloseKey(hSubKey
);
1021 /***** HACK for Windows < Vista (e.g. 2000, Xp, 2003...) *****/
1023 // Save also a valued-entry for the service.
1025 if (bIsWindows
&& bIsPreVistaOSVersion
)
1027 RegSetDWORDValue(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", svcName
, TRUE
, lpServiceConfig
->dwStartType
);
1029 /*************************************************************/
1031 ////////// HACKHACKHACKHACKHACKHACKHACKHACKHACKHACKHACK ///////////
1032 // userModificationsList.RemoveAt(it);
1035 MemFree(lpServiceConfig
);
1036 CloseServiceHandle(hService
);
1039 //////////// HACK HACK !!!! ////////////
1040 userModificationsList
.RemoveAll();
1041 ////////////////////////////////////////
1043 CloseServiceHandle(hSCManager
);
1046 //// PropSheet_UnChanged(GetParent(hServicesPage), hServicesPage); ////
1047 PropSheet_CancelToClose(GetParent(hDlg
));
1049 /* Modifications are OK */
1050 SetWindowLongPtr(hServicesPage
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1054 MessageBox(hDlg
, _T("Impossible to open the SC manager..."), _T("Error"), MB_ICONERROR
);
1056 // There was an error...
1057 SetWindowLongPtr(hServicesPage
, DWLP_MSGRESULT
, PSNRET_INVALID
);
1060 GetServices(bMaskProprietarySvcs
);
1061 UpdateBtnStates(hDlg
);
1068 MessageBox(hServicesPage
, _T("Help not implemented yet!"), _T("Help"), MB_ICONINFORMATION
| MB_OK
);
1072 case PSN_KILLACTIVE
: // Is going to lose activation.
1074 // Changes are always valid of course.
1075 SetWindowLongPtr(hServicesPage
, DWLP_MSGRESULT
, FALSE
);
1079 case PSN_QUERYCANCEL
:
1081 // RefreshStartupList();
1083 // Allows cancellation.
1084 SetWindowLongPtr(hServicesPage
, DWLP_MSGRESULT
, FALSE
);
1089 case PSN_QUERYINITIALFOCUS
:
1091 // Give the focus on and select the first item.
1092 ListView_SetItemState(hServicesListCtrl
, 0, LVIS_FOCUSED
| LVIS_SELECTED
, LVIS_FOCUSED
| LVIS_SELECTED
);
1094 SetWindowLongPtr(hServicesPage
, DWLP_MSGRESULT
, (LONG_PTR
)hServicesListCtrl
);
1099 // DO NOT TOUCH THESE NEXT MESSAGES, THEY ARE OK LIKE THIS...
1101 case PSN_RESET
: // Perform final cleaning, called before WM_DESTROY.
1104 case PSN_SETACTIVE
: // Is going to gain activation.
1106 SetWindowLongPtr(hServicesPage
, DWLP_MSGRESULT
, 0);