Something went wrong. Try again.
Reactos
Something went wrong. Try again.
44 kB · 1123 lines
C++
at master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124/* * 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 BOOLRegisterNoMsgAnymore(VOID){ return (RegSetDWORDValue(HKEY_CURRENT_USER /* HKEY_LOCAL_MACHINE ?? */, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig", L"HideEssentialServiceWarning", TRUE, 1) == ERROR_SUCCESS);}
BOOLHideEssentialServiceWarning(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 CALLBACKRequiredServicesDisablingDialogWndProc(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 voidUpdateBtnStates(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 CALLBACKServicesPageWndProc(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;}
}