mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
1123 lines
43 KiB
C++
1123 lines
43 KiB
C++
/*
|
|
* PROJECT: ReactOS Applications
|
|
* LICENSE: LGPL - See COPYING in the top level directory
|
|
* FILE: base/applications/msconfig_new/srvpage.cpp
|
|
* PURPOSE: Services page message handler
|
|
* COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de>
|
|
* Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr>
|
|
*
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include "utils.h"
|
|
#include "regutils.h"
|
|
#include "stringutils.h"
|
|
// #include "CmdLineParser.h"
|
|
#include "listview.h"
|
|
#include "uxthemesupp.h"
|
|
|
|
#include <winsvc.h>
|
|
|
|
// #include <atlbase.h>
|
|
#include <atlcoll.h>
|
|
#include <atlstr.h>
|
|
|
|
static HWND hServicesPage = NULL;
|
|
static HWND hServicesListCtrl = NULL;
|
|
static int iSortedColumn = 0;
|
|
static BOOL bMaskProprietarySvcs = FALSE;
|
|
|
|
DWORD GetServicesActivation(VOID)
|
|
{
|
|
DWORD dwServices = 0;
|
|
RegGetDWORDValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\state", L"services", &dwServices);
|
|
return dwServices;
|
|
}
|
|
|
|
BOOL SetServicesActivation(DWORD dwState)
|
|
{
|
|
return (RegSetDWORDValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\state", L"services", TRUE, dwState) == ERROR_SUCCESS);
|
|
}
|
|
|
|
static BOOL
|
|
RegisterNoMsgAnymore(VOID)
|
|
{
|
|
return (RegSetDWORDValue(HKEY_CURRENT_USER /* HKEY_LOCAL_MACHINE ?? */,
|
|
L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig",
|
|
L"HideEssentialServiceWarning",
|
|
TRUE, 1) == ERROR_SUCCESS);
|
|
}
|
|
|
|
BOOL
|
|
HideEssentialServiceWarning(VOID)
|
|
{
|
|
BOOL bRetVal = FALSE;
|
|
DWORD dwValue = 0;
|
|
|
|
bRetVal = ( (RegGetDWORDValue(HKEY_CURRENT_USER /* HKEY_LOCAL_MACHINE ?? */,
|
|
L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig",
|
|
L"HideEssentialServiceWarning",
|
|
&dwValue) == ERROR_SUCCESS) &&
|
|
(dwValue == 1) );
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
struct ServiceItem
|
|
{
|
|
ServiceItem(const LPCWSTR lpszSvcName,
|
|
BOOL bIsEnabled,
|
|
BOOL bIsRequired) :
|
|
m_lpszSvcName(lpszSvcName),
|
|
m_bIsEnabled(bIsEnabled),
|
|
m_bIsRequired(bIsRequired)
|
|
{ }
|
|
|
|
~ServiceItem(void)
|
|
{ }
|
|
|
|
CAtlStringW m_lpszSvcName;
|
|
BOOL m_bIsEnabled;
|
|
BOOL m_bIsRequired;
|
|
};
|
|
|
|
struct RegistryDisabledServiceItemParams
|
|
{
|
|
BOOL bIsPresent;
|
|
BOOL bIsKeyed; // bIsKeyed == TRUE for a keyed-registered service ; == FALSE for a valued-registered service.
|
|
DWORD dwStartType;
|
|
SYSTEMTIME time;
|
|
};
|
|
|
|
static CAtlList<CAtlStringW> userModificationsList;
|
|
|
|
QUERY_REGISTRY_VALUES_ROUTINE(GetRegistryValuedDisabledServicesQueryRoutine)
|
|
{
|
|
UNREFERENCED_PARAMETER(KeyName);
|
|
UNREFERENCED_PARAMETER(ValueData);
|
|
UNREFERENCED_PARAMETER(ValueLength);
|
|
|
|
if (!EntryContext)
|
|
return ERROR_SUCCESS;
|
|
|
|
RegistryDisabledServiceItemParams* pContextParams = (RegistryDisabledServiceItemParams*)EntryContext;
|
|
if (pContextParams->bIsPresent)
|
|
return ERROR_SUCCESS;
|
|
|
|
if ( (hRootKey == HKEY_LOCAL_MACHINE) && (ValueType == REG_DWORD) && (ValueLength == sizeof(DWORD)) &&
|
|
(wcsicmp((LPCWSTR)Context, ValueName) == 0) )
|
|
{
|
|
pContextParams->bIsPresent = TRUE;
|
|
pContextParams->bIsKeyed = FALSE;
|
|
pContextParams->dwStartType = *(DWORD*)ValueData;
|
|
// pContextParams->time = {};
|
|
}
|
|
else
|
|
{
|
|
pContextParams->bIsPresent = FALSE;
|
|
pContextParams->bIsKeyed = FALSE;
|
|
pContextParams->dwStartType = 0;
|
|
// pContextParams->time = {};
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
QUERY_REGISTRY_KEYS_ROUTINE(GetRegistryKeyedDisabledServicesQueryRoutine)
|
|
{
|
|
UNREFERENCED_PARAMETER(hRootKey);
|
|
UNREFERENCED_PARAMETER(KeyName);
|
|
|
|
if (!EntryContext)
|
|
return ERROR_SUCCESS;
|
|
|
|
RegistryDisabledServiceItemParams* pContextParams = (RegistryDisabledServiceItemParams*)EntryContext;
|
|
if (pContextParams->bIsPresent)
|
|
return ERROR_SUCCESS;
|
|
|
|
DWORD dwType = 0, dwBufSize = 0;
|
|
|
|
// Be careful, the order of the operations in the comparison is very important.
|
|
if ( (wcsicmp((LPCWSTR)Context, SubKeyName) == 0) &&
|
|
(RegQueryValueEx(hOpenedSubKey, /* ValueName == */ SubKeyName, NULL, &dwType, NULL, &dwBufSize) == ERROR_SUCCESS) &&
|
|
(dwType == REG_DWORD) && (dwBufSize == sizeof(DWORD)) )
|
|
{
|
|
#if 1 // DisableDate
|
|
SYSTEMTIME disableDate = {};
|
|
DWORD dwRegData = 0;
|
|
|
|
dwRegData = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, L"DAY", &dwRegData);
|
|
disableDate.wDay = LOWORD(dwRegData);
|
|
|
|
dwRegData = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, L"HOUR", &dwRegData);
|
|
disableDate.wHour = LOWORD(dwRegData);
|
|
|
|
dwRegData = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, L"MINUTE", &dwRegData);
|
|
disableDate.wMinute = LOWORD(dwRegData);
|
|
|
|
dwRegData = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, L"MONTH", &dwRegData);
|
|
disableDate.wMonth = LOWORD(dwRegData);
|
|
|
|
dwRegData = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, L"SECOND", &dwRegData);
|
|
disableDate.wSecond = LOWORD(dwRegData);
|
|
|
|
dwRegData = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, L"YEAR", &dwRegData);
|
|
disableDate.wYear = LOWORD(dwRegData);
|
|
#endif
|
|
|
|
DWORD dwStartType = 0;
|
|
RegGetDWORDValue(hOpenedSubKey, NULL, SubKeyName /* Service name */, &dwStartType);
|
|
|
|
pContextParams->bIsPresent = TRUE;
|
|
pContextParams->bIsKeyed = TRUE;
|
|
pContextParams->dwStartType = dwStartType;
|
|
pContextParams->time = disableDate;
|
|
}
|
|
else
|
|
{
|
|
pContextParams->bIsPresent = FALSE;
|
|
pContextParams->bIsKeyed = TRUE;
|
|
pContextParams->dwStartType = 0;
|
|
// pContextParams->time = {};
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
static void AddService(SC_HANDLE hSCManager, LPENUM_SERVICE_STATUS_PROCESS Service, BOOL bHideOSVendorServices)
|
|
{
|
|
//
|
|
// Retrieve a handle to the service.
|
|
//
|
|
SC_HANDLE hService = OpenServiceW(hSCManager, Service->lpServiceName, SERVICE_QUERY_CONFIG);
|
|
if (hService == NULL)
|
|
return;
|
|
|
|
DWORD dwBytesNeeded = 0;
|
|
QueryServiceConfigW(hService, NULL, 0, &dwBytesNeeded);
|
|
// if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
LPQUERY_SERVICE_CONFIG lpServiceConfig = (LPQUERY_SERVICE_CONFIG)MemAlloc(0, dwBytesNeeded);
|
|
if (!lpServiceConfig)
|
|
{
|
|
CloseServiceHandle(hService);
|
|
return;
|
|
}
|
|
QueryServiceConfigW(hService, lpServiceConfig, dwBytesNeeded, &dwBytesNeeded);
|
|
|
|
//
|
|
// Get the service's vendor...
|
|
//
|
|
LPWSTR lpszVendor = NULL;
|
|
{
|
|
// Isolate only the executable path, without any arguments.
|
|
// TODO: Correct at the level of CmdLineToArgv the potential bug when lpszFilename == NULL.
|
|
#if 0 // Disabled until CmdLineToArgv is included
|
|
unsigned int argc = 0;
|
|
LPWSTR* argv = NULL;
|
|
CmdLineToArgv(lpServiceConfig->lpBinaryPathName, &argc, &argv, L" \t");
|
|
if (argc >= 1 && argv[0])
|
|
lpszVendor = GetExecutableVendor(argv[0]);
|
|
#else
|
|
// Hackish solution taken from the original srvpage.c.
|
|
// Will be removed after CmdLineToArgv is introduced.
|
|
WCHAR FileName[MAX_PATH];
|
|
memset(&FileName, 0, sizeof(FileName));
|
|
if (wcscspn(lpServiceConfig->lpBinaryPathName, L"\""))
|
|
{
|
|
wcsncpy(FileName, lpServiceConfig->lpBinaryPathName, wcscspn(lpServiceConfig->lpBinaryPathName, L" ") );
|
|
}
|
|
else
|
|
{
|
|
wcscpy(FileName, lpServiceConfig->lpBinaryPathName);
|
|
}
|
|
lpszVendor = GetExecutableVendor(FileName);
|
|
#endif
|
|
if (!lpszVendor)
|
|
lpszVendor = LoadResourceString(hInst, IDS_UNKNOWN);
|
|
#if 0
|
|
MemFree(argv);
|
|
#endif
|
|
}
|
|
|
|
// ...and display or not the Microsoft / ReactOS services.
|
|
BOOL bContinue = TRUE;
|
|
if (bHideOSVendorServices)
|
|
{
|
|
if (FindSubStrI(lpszVendor, bIsWindows ? IDS_MICROSOFT : IDS_REACTOS))
|
|
bContinue = FALSE;
|
|
}
|
|
|
|
if (bContinue)
|
|
{
|
|
BOOL bIsServiceEnabled = (lpServiceConfig->dwStartType != SERVICE_DISABLED);
|
|
BOOL bAddServiceToList = FALSE;
|
|
BOOL bIsModifiedService = FALSE;
|
|
RegistryDisabledServiceItemParams params = {};
|
|
|
|
//
|
|
// Try to look into the user modifications list...
|
|
//
|
|
POSITION it = userModificationsList.Find(Service->lpServiceName);
|
|
if (it)
|
|
{
|
|
bAddServiceToList = TRUE;
|
|
bIsModifiedService = TRUE;
|
|
}
|
|
|
|
//
|
|
// ...if not found, try to find if the disabled service is in the registry.
|
|
//
|
|
if (!bAddServiceToList)
|
|
{
|
|
if (!bIsServiceEnabled)
|
|
{
|
|
QUERY_REGISTRY_KEYS_TABLE KeysQueryTable[2] = {};
|
|
KeysQueryTable[0].QueryRoutine = GetRegistryKeyedDisabledServicesQueryRoutine;
|
|
KeysQueryTable[0].EntryContext = ¶ms;
|
|
RegQueryRegistryKeys(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", KeysQueryTable, Service->lpServiceName);
|
|
|
|
bAddServiceToList = params.bIsPresent;
|
|
|
|
if (bIsWindows && bIsPreVistaOSVersion && !bAddServiceToList)
|
|
{
|
|
QUERY_REGISTRY_VALUES_TABLE ValuesQueryTable[2] = {};
|
|
ValuesQueryTable[0].QueryRoutine = GetRegistryValuedDisabledServicesQueryRoutine;
|
|
ValuesQueryTable[0].EntryContext = ¶ms;
|
|
RegQueryRegistryValues(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", ValuesQueryTable, Service->lpServiceName);
|
|
|
|
bAddServiceToList = params.bIsPresent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bAddServiceToList = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bAddServiceToList)
|
|
{
|
|
//
|
|
// Check if service is required by the system.
|
|
//
|
|
BOOL bIsRequired = FALSE;
|
|
|
|
dwBytesNeeded = 0;
|
|
QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, NULL, 0, &dwBytesNeeded);
|
|
// if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
LPSERVICE_FAILURE_ACTIONS lpServiceFailureActions = (LPSERVICE_FAILURE_ACTIONS)MemAlloc(0, dwBytesNeeded);
|
|
if (!lpServiceFailureActions)
|
|
{
|
|
MemFree(lpszVendor);
|
|
MemFree(lpServiceConfig);
|
|
CloseServiceHandle(hService);
|
|
return;
|
|
}
|
|
|
|
QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)lpServiceFailureActions, dwBytesNeeded, &dwBytesNeeded);
|
|
|
|
// In Microsoft's MSConfig, things are done just like that!! (extracted string values from msconfig.exe)
|
|
if ( ( wcsicmp(Service->lpServiceName, L"rpcss" ) == 0 ||
|
|
wcsicmp(Service->lpServiceName, L"rpclocator") == 0 ||
|
|
wcsicmp(Service->lpServiceName, L"dcomlaunch") == 0 ) ||
|
|
( lpServiceFailureActions &&
|
|
(lpServiceFailureActions->cActions >= 1) &&
|
|
(lpServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT) ) ) // We add also this test, which corresponds to real life.
|
|
{
|
|
bIsRequired = TRUE;
|
|
}
|
|
MemFree(lpServiceFailureActions);
|
|
|
|
//
|
|
// Add the service into the list.
|
|
//
|
|
LVITEM item = {};
|
|
item.mask = LVIF_TEXT | LVIF_PARAM;
|
|
item.pszText = Service->lpDisplayName;
|
|
item.lParam = reinterpret_cast<LPARAM>(new ServiceItem(Service->lpServiceName, bIsServiceEnabled, bIsRequired));
|
|
item.iItem = ListView_InsertItem(hServicesListCtrl, &item);
|
|
|
|
if (bIsRequired)
|
|
{
|
|
LPWSTR lpszYes = LoadResourceString(hInst, IDS_YES);
|
|
ListView_SetItemText(hServicesListCtrl, item.iItem, 1, lpszYes);
|
|
MemFree(lpszYes);
|
|
}
|
|
|
|
ListView_SetItemText(hServicesListCtrl, item.iItem, 2, lpszVendor);
|
|
|
|
LPWSTR lpszStatus = LoadResourceString(hInst, ((Service->ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED) ? IDS_SERVICES_STATUS_STOPPED : IDS_SERVICES_STATUS_RUNNING));
|
|
ListView_SetItemText(hServicesListCtrl, item.iItem, 3, lpszStatus);
|
|
MemFree(lpszStatus);
|
|
|
|
if (!bIsServiceEnabled)
|
|
{
|
|
LPWSTR lpszUnknown = LoadResourceString(hInst, IDS_UNKNOWN);
|
|
|
|
LPWSTR lpszDisableDate = FormatDateTime(¶ms.time);
|
|
ListView_SetItemText(hServicesListCtrl, item.iItem, 4, (lpszDisableDate ? lpszDisableDate : lpszUnknown));
|
|
FreeDateTime(lpszDisableDate);
|
|
|
|
MemFree(lpszUnknown);
|
|
}
|
|
|
|
ListView_SetCheckState(hServicesListCtrl, item.iItem, (!bIsModifiedService ? bIsServiceEnabled : !bIsServiceEnabled));
|
|
}
|
|
}
|
|
|
|
MemFree(lpszVendor);
|
|
MemFree(lpServiceConfig);
|
|
CloseServiceHandle(hService);
|
|
|
|
return;
|
|
}
|
|
|
|
static void ClearServicesList(void)
|
|
{
|
|
LVITEM lvitem = {};
|
|
lvitem.mask = LVIF_PARAM;
|
|
lvitem.iItem = -1; // From the beginning.
|
|
|
|
while ((lvitem.iItem = ListView_GetNextItem(hServicesListCtrl, lvitem.iItem, LVNI_ALL)) != -1)
|
|
{
|
|
ListView_GetItem(hServicesListCtrl, &lvitem);
|
|
|
|
delete reinterpret_cast<ServiceItem*>(lvitem.lParam);
|
|
lvitem.lParam = NULL;
|
|
}
|
|
ListView_DeleteAllItems(hServicesListCtrl);
|
|
|
|
return;
|
|
}
|
|
|
|
static void GetServices(BOOL bHideOSVendorServices = FALSE)
|
|
{
|
|
//
|
|
// First of all, clear the list.
|
|
//
|
|
ClearServicesList();
|
|
|
|
//
|
|
// Now, we can list the services.
|
|
//
|
|
|
|
// Open the Service Control Manager.
|
|
SC_HANDLE hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
|
|
if (hSCManager == NULL)
|
|
return;
|
|
|
|
// Enumerate all the Win32 services.
|
|
DWORD dwBytesNeeded = 0;
|
|
DWORD dwNumServices = 0;
|
|
// DWORD dwResumeHandle = 0;
|
|
EnumServicesStatusExW(hSCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &dwBytesNeeded, &dwNumServices, NULL /* &dwResumeHandle */, NULL);
|
|
// if (GetLastError() == ERROR_MORE_DATA)
|
|
|
|
LPENUM_SERVICE_STATUS_PROCESS lpServices = (LPENUM_SERVICE_STATUS_PROCESS)MemAlloc(0, dwBytesNeeded);
|
|
if (!lpServices)
|
|
{
|
|
CloseServiceHandle(hSCManager);
|
|
return;
|
|
}
|
|
EnumServicesStatusExW(hSCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)lpServices, dwBytesNeeded, &dwBytesNeeded, &dwNumServices, NULL /* &dwResumeHandle */, NULL);
|
|
|
|
// Add them into the list.
|
|
for (DWORD i = 0 ; i < dwNumServices ; ++i)
|
|
{
|
|
AddService(hSCManager, lpServices + i, bHideOSVendorServices);
|
|
}
|
|
|
|
// Cleaning.
|
|
MemFree(lpServices);
|
|
CloseServiceHandle(hSCManager);
|
|
|
|
return;
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
RequiredServicesDisablingDialogWndProc(HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
/* Correctly display message strings */
|
|
LPCWSTR szOSVendor;
|
|
size_t itemLength = 0;
|
|
LPWSTR szItem = NULL, szNewItem = NULL;
|
|
|
|
szOSVendor = (bIsWindows ? IDS_WINDOWS : IDS_REACTOS);
|
|
|
|
itemLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_STATIC_REQSVCSDIS_INFO)) + 1;
|
|
szItem = (LPWSTR)MemAlloc(0, itemLength * sizeof(WCHAR));
|
|
GetDlgItemText(hDlg, IDC_STATIC_REQSVCSDIS_INFO, szItem, (int)itemLength);
|
|
szNewItem = FormatString(szItem, szOSVendor);
|
|
SetDlgItemText(hDlg, IDC_STATIC_REQSVCSDIS_INFO, szNewItem);
|
|
MemFree(szNewItem);
|
|
MemFree(szItem);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
{
|
|
if (Button_GetCheck(GetDlgItem(hDlg, IDC_CBX_REQSVCSDIS_NO_MSG_ANYMORE)) == BST_CHECKED)
|
|
RegisterNoMsgAnymore();
|
|
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
|
|
default:
|
|
//break;
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL ValidateItem(int index, BOOL bNewState, BOOL bDisplayErrors)
|
|
{
|
|
ServiceItem* pSvcItem = NULL;
|
|
|
|
LVITEM truc = {};
|
|
truc.mask = LVIF_PARAM;
|
|
truc.iItem = index;
|
|
ListView_GetItem(hServicesListCtrl, &truc);
|
|
|
|
// The lParam member must be valid.
|
|
pSvcItem = reinterpret_cast<ServiceItem*>(truc.lParam);
|
|
if (!pSvcItem)
|
|
return FALSE;
|
|
|
|
//
|
|
// Allow modifications only if the service is not a required service for the system,
|
|
// or allow only the activation of a disabled required service.
|
|
//
|
|
BOOL bOldState = !!(ListView_GetCheckState(hServicesListCtrl, truc.iItem /* == index */) % 2);
|
|
|
|
if ( !pSvcItem->m_bIsRequired ||
|
|
(pSvcItem->m_bIsRequired && !pSvcItem->m_bIsEnabled && bOldState == FALSE && bNewState == TRUE) )
|
|
{
|
|
if (bOldState == bNewState)
|
|
return FALSE;
|
|
|
|
ListView_SetCheckState(hServicesListCtrl, index, bNewState);
|
|
|
|
if (pSvcItem->m_bIsEnabled) // Enabled service.
|
|
{
|
|
if (bNewState == FALSE) // To be deactivated.
|
|
{
|
|
userModificationsList.AddTail(pSvcItem->m_lpszSvcName);
|
|
}
|
|
else if (bNewState == TRUE) // To be reactivated
|
|
{
|
|
POSITION it = userModificationsList.Find(pSvcItem->m_lpszSvcName);
|
|
if (it)
|
|
{
|
|
userModificationsList.RemoveAt(it);
|
|
}
|
|
else
|
|
{
|
|
OutputDebugString(_T("(1) \"WTF: What The Fukhurmajalmahamadahaldeliya ?!\" (The Dictator, Sacha Baron Cohen)\n"));
|
|
}
|
|
}
|
|
}
|
|
else // Disabled service.
|
|
{
|
|
if (bNewState == TRUE) // To be activated.
|
|
{
|
|
userModificationsList.AddTail(pSvcItem->m_lpszSvcName);
|
|
}
|
|
else if (bNewState == FALSE) // To be redeactivated
|
|
{
|
|
POSITION it = userModificationsList.Find(pSvcItem->m_lpszSvcName);
|
|
if (it)
|
|
{
|
|
userModificationsList.RemoveAt(it);
|
|
}
|
|
else
|
|
{
|
|
OutputDebugString(_T("(2) \"WTF: What The Fukhurmajalmahamadahaldeliya ?!\" (The Dictator, Sacha Baron Cohen)\n"));
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (bDisplayErrors)
|
|
{
|
|
DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_REQUIRED_SERVICES_DISABLING_DIALOG), hServicesPage /* hMainWnd */, RequiredServicesDisablingDialogWndProc);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
UpdateBtnStates(HWND hDlg)
|
|
{
|
|
// HWND hTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE);
|
|
|
|
//
|
|
// "Enable all" / "Disable all" buttons.
|
|
//
|
|
// UINT uRootCheckState = TreeView_GetRealSubtreeState(hTree, TVI_ROOT);
|
|
UINT uRootCheckState = ListView_GetCheckState(hServicesListCtrl, 0);
|
|
#define OP(a, b) ((a) == (b) ? (a) : 2)
|
|
int index = 0; // -1 // From the beginning + 1.
|
|
while ((index = ListView_GetNextItem(hServicesListCtrl, index, LVNI_ALL)) != -1)
|
|
{
|
|
UINT temp = ListView_GetCheckState(hServicesListCtrl, index);
|
|
uRootCheckState = OP(uRootCheckState, temp);
|
|
}
|
|
|
|
if (uRootCheckState == 0)
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_ACTIVATE) , TRUE );
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_DEACTIVATE), FALSE);
|
|
}
|
|
else if (uRootCheckState == 1)
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_ACTIVATE) , FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_DEACTIVATE), TRUE );
|
|
}
|
|
else if (uRootCheckState == 2)
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_ACTIVATE) , TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_DEACTIVATE), TRUE);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_ACTIVATE) , FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SERVICES_DEACTIVATE), FALSE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
INT_PTR CALLBACK
|
|
ServicesPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
hServicesPage = hDlg;
|
|
hServicesListCtrl = GetDlgItem(hServicesPage, IDC_SERVICES_LIST);
|
|
|
|
//
|
|
// Correctly display message strings.
|
|
//
|
|
LPCWSTR szOSVendor = (bIsWindows ? IDS_MICROSOFT : IDS_REACTOS);
|
|
|
|
size_t itemLength = 0;
|
|
LPWSTR szItem = NULL, szNewItem = NULL;
|
|
|
|
itemLength = GetWindowTextLength(GetDlgItem(hServicesPage, IDC_STATIC_SERVICES_WARNING)) + 1;
|
|
szItem = (LPWSTR)MemAlloc(0, itemLength * sizeof(WCHAR));
|
|
GetDlgItemText(hServicesPage, IDC_STATIC_SERVICES_WARNING, szItem, (int)itemLength);
|
|
szNewItem = FormatString(szItem, szOSVendor);
|
|
SetDlgItemText(hServicesPage, IDC_STATIC_SERVICES_WARNING, szNewItem);
|
|
MemFree(szNewItem);
|
|
MemFree(szItem);
|
|
|
|
itemLength = GetWindowTextLength(GetDlgItem(hServicesPage, IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS)) + 1;
|
|
szItem = (LPWSTR)MemAlloc(0, itemLength * sizeof(WCHAR));
|
|
GetDlgItemText(hServicesPage, IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS, szItem, (int)itemLength);
|
|
szNewItem = FormatString(szItem, szOSVendor);
|
|
SetDlgItemText(hServicesPage, IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS, szNewItem);
|
|
MemFree(szNewItem);
|
|
MemFree(szItem);
|
|
|
|
//
|
|
// Initialize the styles.
|
|
//
|
|
DWORD dwStyle = ListView_GetExtendedListViewStyle(hServicesListCtrl);
|
|
ListView_SetExtendedListViewStyle(hServicesListCtrl, dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
|
|
SetWindowTheme(hServicesListCtrl, L"Explorer", NULL);
|
|
|
|
//
|
|
// Initialize the application page's controls.
|
|
//
|
|
LVCOLUMN column = {};
|
|
|
|
// First column : Service's name.
|
|
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
column.pszText = LoadResourceString(hInst, IDS_SERVICES_COLUMN_SERVICE);
|
|
column.cx = 150;
|
|
ListView_InsertColumn(hServicesListCtrl, 0, &column);
|
|
MemFree(column.pszText);
|
|
|
|
// Second column : Whether the service is required or not.
|
|
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
column.pszText = LoadResourceString(hInst, IDS_SERVICES_COLUMN_REQ);
|
|
column.cx = 60;
|
|
ListView_InsertColumn(hServicesListCtrl, 1, &column);
|
|
MemFree(column.pszText);
|
|
|
|
// Third column : Service's vendor.
|
|
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
column.pszText = LoadResourceString(hInst, IDS_SERVICES_COLUMN_VENDOR);
|
|
column.cx = 150;
|
|
ListView_InsertColumn(hServicesListCtrl, 2, &column);
|
|
MemFree(column.pszText);
|
|
|
|
// Fourth column : Service's status.
|
|
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
column.pszText = LoadResourceString(hInst, IDS_SERVICES_COLUMN_STATUS);
|
|
column.cx = 60;
|
|
ListView_InsertColumn(hServicesListCtrl, 3, &column);
|
|
MemFree(column.pszText);
|
|
|
|
// Fifth column : Service's disabled date.
|
|
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
column.pszText = LoadResourceString(hInst, IDS_SERVICES_COLUMN_DATEDISABLED);
|
|
column.cx = 120;
|
|
ListView_InsertColumn(hServicesListCtrl, 4, &column);
|
|
MemFree(column.pszText);
|
|
|
|
//
|
|
// Populate and sort the list.
|
|
//
|
|
GetServices();
|
|
ListView_Sort(hServicesListCtrl, 0);
|
|
UpdateBtnStates(hDlg);
|
|
|
|
// Select the first item.
|
|
ListView_SetItemState(hServicesListCtrl, 0, LVIS_SELECTED, LVIS_SELECTED);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
ClearServicesList();
|
|
userModificationsList.RemoveAll();
|
|
return 0;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_BTN_SERVICES_ACTIVATE:
|
|
{
|
|
BOOL bAreThereMods = FALSE;
|
|
|
|
int index = -1; // From the beginning.
|
|
while ((index = ListView_GetNextItem(hServicesListCtrl, index, LVNI_ALL)) != -1)
|
|
{
|
|
bAreThereMods = ValidateItem(index, TRUE, FALSE) || bAreThereMods; // The order is verrrrrry important !!!!
|
|
}
|
|
|
|
if (bAreThereMods)
|
|
{
|
|
UpdateBtnStates(hDlg);
|
|
PropSheet_Changed(GetParent(hServicesPage), hServicesPage);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case IDC_BTN_SERVICES_DEACTIVATE:
|
|
{
|
|
BOOL bAreThereMods = FALSE;
|
|
|
|
int index = -1; // From the beginning.
|
|
while ((index = ListView_GetNextItem(hServicesListCtrl, index, LVNI_ALL)) != -1)
|
|
{
|
|
bAreThereMods = ValidateItem(index, FALSE, FALSE) || bAreThereMods; // The order is verrrrrry important !!!!
|
|
}
|
|
|
|
if (bAreThereMods)
|
|
{
|
|
UpdateBtnStates(hDlg);
|
|
PropSheet_Changed(GetParent(hServicesPage), hServicesPage);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS:
|
|
{
|
|
bMaskProprietarySvcs = !bMaskProprietarySvcs;
|
|
GetServices(bMaskProprietarySvcs);
|
|
UpdateBtnStates(hDlg);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
case UM_CHECKSTATECHANGE:
|
|
{
|
|
BOOL bNewCheckState = !!((ListView_GetCheckState(hServicesListCtrl, int(lParam)) + 1) % 2);
|
|
|
|
if (ValidateItem(/*reinterpret_cast<int>*/ int(lParam), bNewCheckState, !HideEssentialServiceWarning()))
|
|
{
|
|
UpdateBtnStates(hDlg);
|
|
PropSheet_Changed(GetParent(hServicesPage), hServicesPage);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
if (reinterpret_cast<LPNMHDR>(lParam)->hwndFrom == hServicesListCtrl)
|
|
{
|
|
switch (reinterpret_cast<LPNMHDR>(lParam)->code)
|
|
{
|
|
case NM_CLICK:
|
|
case NM_RCLICK:
|
|
{
|
|
DWORD dwpos = GetMessagePos();
|
|
LVHITTESTINFO ht = {};
|
|
ht.pt.x = GET_X_LPARAM(dwpos);
|
|
ht.pt.y = GET_Y_LPARAM(dwpos);
|
|
MapWindowPoints(HWND_DESKTOP /*NULL*/, hServicesListCtrl, &ht.pt, 1);
|
|
|
|
/*
|
|
* We use ListView_SubItemHitTest(...) and not ListView_HitTest(...)
|
|
* because ListView_HitTest(...) returns bad flags when one clicks
|
|
* on a sub-item different from 0. The flags then contain LVHT_ONITEMSTATEICON
|
|
* which must not be obviously present in this case.
|
|
*/
|
|
ListView_SubItemHitTest(hServicesListCtrl, &ht);
|
|
|
|
if (LVHT_ONITEMSTATEICON & ht.flags)
|
|
{
|
|
PostMessage(hDlg, UM_CHECKSTATECHANGE, 0, (LPARAM)ht.iItem);
|
|
|
|
// Disable default behaviour. Needed for the UM_CHECKSTATECHANGE
|
|
// custom notification to work as expected.
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case NM_DBLCLK:
|
|
case NM_RDBLCLK:
|
|
{
|
|
// We deactivate double-clicks.
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
case LVN_KEYDOWN:
|
|
{
|
|
if (reinterpret_cast<LPNMLVKEYDOWN>(lParam)->wVKey == VK_SPACE)
|
|
{
|
|
int iItem = ListView_GetSelectionMark(hServicesListCtrl);
|
|
PostMessage(hDlg, UM_CHECKSTATECHANGE, 0, (LPARAM)iItem);
|
|
|
|
// Disable default behaviour. Needed for the UM_CHECKSTATECHANGE
|
|
// custom notification to work as expected.
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
int iSortingColumn = reinterpret_cast<LPNMLISTVIEW>(lParam)->iSubItem;
|
|
|
|
ListView_SortEx(hServicesListCtrl, iSortingColumn, iSortedColumn);
|
|
iSortedColumn = iSortingColumn;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (reinterpret_cast<LPNMHDR>(lParam)->code)
|
|
{
|
|
case PSN_APPLY:
|
|
{
|
|
// Try to apply the modifications to the system.
|
|
MessageBox(NULL, _T("In Services page: PSN_APPLY"), _T("Info"), MB_ICONINFORMATION);
|
|
|
|
/*
|
|
//
|
|
// Move this away...
|
|
//
|
|
int iRetVal = MessageBox(NULL, _T("Would you really want to modify the configuration of your system ?"), _T("Warning"), MB_ICONWARNING | MB_YESNOCANCEL);
|
|
|
|
if (iRetVal == IDYES /\* modifications are OK *\/)
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
else if (iRetVal == IDNO /\* modifications are not OK *\/)
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
else // if (iRetVal == IDCANCEL) // There was an error...
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_INVALID);
|
|
*/
|
|
|
|
//
|
|
// We modify the services which are stored in the user modification list.
|
|
//
|
|
|
|
// 1- Open the Service Control Manager for modifications.
|
|
SC_HANDLE hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
if (hSCManager != NULL)
|
|
{
|
|
LPCWSTR svcName;
|
|
|
|
for (POSITION it = userModificationsList.GetHeadPosition(); it; userModificationsList.GetNext(it))
|
|
{
|
|
svcName = userModificationsList.GetAt(it);
|
|
|
|
// 2- Retrieve a handle to the service.
|
|
SC_HANDLE hService = OpenServiceW(hSCManager, svcName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
|
|
if (hService == NULL)
|
|
{
|
|
// TODO : Show a message box.
|
|
continue;
|
|
}
|
|
|
|
DWORD dwBytesNeeded = 0;
|
|
QueryServiceConfigW(hService, NULL, 0, &dwBytesNeeded);
|
|
// if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
LPQUERY_SERVICE_CONFIG lpServiceConfig = (LPQUERY_SERVICE_CONFIG)MemAlloc(0, dwBytesNeeded);
|
|
if (!lpServiceConfig)
|
|
{
|
|
CloseServiceHandle(hService);
|
|
continue; // TODO ? Show a message box...
|
|
}
|
|
QueryServiceConfigW(hService, lpServiceConfig, dwBytesNeeded, &dwBytesNeeded);
|
|
|
|
if (lpServiceConfig->dwStartType == SERVICE_DISABLED) // We have a disabled service which is becoming to be enabled.
|
|
{
|
|
// 3a- Retrieve the properties of the disabled service from the registry.
|
|
RegistryDisabledServiceItemParams params = {};
|
|
|
|
QUERY_REGISTRY_KEYS_TABLE KeysQueryTable[2] = {};
|
|
KeysQueryTable[0].QueryRoutine = GetRegistryKeyedDisabledServicesQueryRoutine;
|
|
KeysQueryTable[0].EntryContext = ¶ms;
|
|
RegQueryRegistryKeys(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", KeysQueryTable, (PVOID)svcName);
|
|
|
|
if (bIsWindows && bIsPreVistaOSVersion && !params.bIsPresent)
|
|
{
|
|
QUERY_REGISTRY_VALUES_TABLE ValuesQueryTable[2] = {};
|
|
ValuesQueryTable[0].QueryRoutine = GetRegistryValuedDisabledServicesQueryRoutine;
|
|
ValuesQueryTable[0].EntryContext = ¶ms;
|
|
RegQueryRegistryValues(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", ValuesQueryTable, (PVOID)svcName);
|
|
}
|
|
|
|
if (params.bIsPresent)
|
|
{
|
|
// 4a- Modify the service.
|
|
ChangeServiceConfigW(hService, SERVICE_NO_CHANGE, params.dwStartType, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
// 5a- Remove the registry entry of the service.
|
|
if (params.bIsKeyed)
|
|
{
|
|
CAtlStringW serviceRegKey(L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services\\");
|
|
serviceRegKey += svcName;
|
|
RegDeleteKeyW(HKEY_LOCAL_MACHINE, serviceRegKey);
|
|
|
|
/***** HACK for Windows < Vista (e.g. 2000, Xp, 2003...) *****/
|
|
//
|
|
// Delete also the valued-entry of the service.
|
|
//
|
|
if (bIsWindows && bIsPreVistaOSVersion)
|
|
{
|
|
HKEY hSubKey = NULL;
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", 0, KEY_SET_VALUE /*KEY_READ*/, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
RegDeleteValue(hSubKey, svcName);
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
}
|
|
/*************************************************************/
|
|
}
|
|
else
|
|
{
|
|
HKEY hSubKey = NULL;
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", 0, KEY_SET_VALUE /*KEY_READ*/, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
RegDeleteValue(hSubKey, svcName);
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
}
|
|
|
|
////////// HACKHACKHACKHACKHACKHACKHACKHACKHACKHACKHACK ///////////
|
|
// userModificationsList.RemoveAt(it);
|
|
}
|
|
else
|
|
{
|
|
// Ohoh !! We have a very big problem.
|
|
MessageBox(NULL, _T("WTF ??"), _T("FATAL ERROR !!!!"), MB_ICONERROR);
|
|
}
|
|
}
|
|
else // We have an enabled service which is becoming to be disabled.
|
|
{
|
|
// 3b- Retrieve the local time of disabling.
|
|
SYSTEMTIME disableDate = {};
|
|
GetLocalTime(&disableDate);
|
|
|
|
// 4b- Modify the service.
|
|
ChangeServiceConfigW(hService, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
// 5b- Register the service into the registry.
|
|
CAtlStringW serviceRegKey(L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services\\");
|
|
serviceRegKey += svcName;
|
|
HKEY hSubKey = NULL;
|
|
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, serviceRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
RegSetDWORDValue(hSubKey, NULL, svcName, FALSE, lpServiceConfig->dwStartType);
|
|
|
|
#if 1 // DisableDate
|
|
RegSetDWORDValue(hSubKey, NULL, L"DAY" , FALSE, disableDate.wDay );
|
|
RegSetDWORDValue(hSubKey, NULL, L"HOUR" , FALSE, disableDate.wHour );
|
|
RegSetDWORDValue(hSubKey, NULL, L"MINUTE", FALSE, disableDate.wMinute);
|
|
RegSetDWORDValue(hSubKey, NULL, L"MONTH" , FALSE, disableDate.wMonth );
|
|
RegSetDWORDValue(hSubKey, NULL, L"SECOND", FALSE, disableDate.wSecond);
|
|
RegSetDWORDValue(hSubKey, NULL, L"YEAR" , FALSE, disableDate.wYear );
|
|
#endif
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
/***** HACK for Windows < Vista (e.g. 2000, Xp, 2003...) *****/
|
|
//
|
|
// Save also a valued-entry for the service.
|
|
//
|
|
if (bIsWindows && bIsPreVistaOSVersion)
|
|
{
|
|
RegSetDWORDValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\services", svcName, TRUE, lpServiceConfig->dwStartType);
|
|
}
|
|
/*************************************************************/
|
|
|
|
////////// HACKHACKHACKHACKHACKHACKHACKHACKHACKHACKHACK ///////////
|
|
// userModificationsList.RemoveAt(it);
|
|
}
|
|
|
|
MemFree(lpServiceConfig);
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
//////////// HACK HACK !!!! ////////////
|
|
userModificationsList.RemoveAll();
|
|
////////////////////////////////////////
|
|
|
|
CloseServiceHandle(hSCManager);
|
|
|
|
|
|
//// PropSheet_UnChanged(GetParent(hServicesPage), hServicesPage); ////
|
|
PropSheet_CancelToClose(GetParent(hDlg));
|
|
|
|
/* Modifications are OK */
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hDlg, _T("Impossible to open the SC manager..."), _T("Error"), MB_ICONERROR);
|
|
|
|
// There was an error...
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, PSNRET_INVALID);
|
|
}
|
|
|
|
GetServices(bMaskProprietarySvcs);
|
|
UpdateBtnStates(hDlg);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case PSN_HELP:
|
|
{
|
|
MessageBox(hServicesPage, _T("Help not implemented yet!"), _T("Help"), MB_ICONINFORMATION | MB_OK);
|
|
return TRUE;
|
|
}
|
|
|
|
case PSN_KILLACTIVE: // Is going to lose activation.
|
|
{
|
|
// Changes are always valid of course.
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
case PSN_QUERYCANCEL:
|
|
{
|
|
// RefreshStartupList();
|
|
|
|
// Allows cancellation.
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case PSN_QUERYINITIALFOCUS:
|
|
{
|
|
// Give the focus on and select the first item.
|
|
ListView_SetItemState(hServicesListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
|
|
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, (LONG_PTR)hServicesListCtrl);
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// DO NOT TOUCH THESE NEXT MESSAGES, THEY ARE OK LIKE THIS...
|
|
//
|
|
case PSN_RESET: // Perform final cleaning, called before WM_DESTROY.
|
|
return TRUE;
|
|
|
|
case PSN_SETACTIVE: // Is going to gain activation.
|
|
{
|
|
SetWindowLongPtr(hServicesPage, DWLP_MSGRESULT, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
}
|