//--------------------------------------------------------------------------- Service & Service::install(SC_HANDLE hSCManager) { install(); utf8::WideString serviceNameW(serviceName_.getUNICODEString()); utf8::WideString displayNameW(displayName_.getUNICODEString()); utf8::WideString binaryPathNameW((!args_.isNull() ? binaryPathName_ + args_ : binaryPathName_).getUNICODEString()); utf8::WideString loadOrderGroupW(loadOrderGroup_.getUNICODEString()); utf8::WideString dependenciesW(dependencies_.getUNICODEString()); utf8::WideString serviceStartNameW(serviceStartName_.getUNICODEString()); utf8::WideString passwordW(password_.getUNICODEString()); SC_HANDLE handle = CreateServiceW( hSCManager, serviceNameW, displayNameW, SERVICE_ALL_ACCESS, serviceType_, startType_, errorControl_, binaryPathNameW, !loadOrderGroup_.isNull() ? (wchar_t *) loadOrderGroupW : NULL, (serviceType_ == SERVICE_KERNEL_DRIVER || serviceType_ == SERVICE_FILE_SYSTEM_DRIVER) && (startType_ == SERVICE_BOOT_START || startType_ == SERVICE_SYSTEM_START) ? &tagId_ : NULL, !dependencies_.isNull() ? (wchar_t *) dependenciesW : NULL, !serviceStartName_.isNull() ? (wchar_t *) serviceStartNameW : NULL, !password_.isNull() ? (wchar_t *) passwordW : NULL ); if( handle == NULL ){ int32_t err = GetLastError(); if( err == ERROR_SERVICE_EXISTS ){ SetLastError(err = ERROR_SUCCESS); handle = OpenServiceW(hSCManager,serviceNameW,SERVICE_ALL_ACCESS); if( handle == NULL || ChangeServiceConfigW(handle, serviceType_, startType_, errorControl_, binaryPathNameW, !loadOrderGroup_.isNull() ? (wchar_t *) loadOrderGroupW : NULL, (serviceType_ == SERVICE_KERNEL_DRIVER || serviceType_ == SERVICE_FILE_SYSTEM_DRIVER) && (startType_ == SERVICE_BOOT_START || startType_ == SERVICE_SYSTEM_START) ? &tagId_ : NULL, !dependencies_.isNull() ? (wchar_t *) dependenciesW : NULL, !serviceStartName_.isNull() ? (wchar_t *) serviceStartNameW : NULL, !password_.isNull() ? (wchar_t *) passwordW : NULL, displayNameW ) == 0 ) err = GetLastError(); } if( err != ERROR_SUCCESS ){ if( handle != NULL ) CloseServiceHandle(handle); newObjectV1C2<Exception>(err + errorOffset,__PRETTY_FUNCTION__)->throwSP(); } } CloseServiceHandle(handle); return *this; }
/** * Determines if the MozillaMaintenance service path needs to be updated * and fixes it if it is wrong. * * @param service A handle to the service to fix. * @param currentServicePath The current (possibly wrong) path that is used. * @param servicePathWasWrong Out parameter set to TRUE if a fix was needed. * @return TRUE if the service path is now correct. */ BOOL FixServicePath(SC_HANDLE service, LPCWSTR currentServicePath, BOOL &servicePathWasWrong) { // When we originally upgraded the MozillaMaintenance service we // would uninstall the service on each upgrade. This had an // intermittent error which could cause the service to use the file // maintenanceservice_tmp.exe as the install path. Only a small number // of Nightly users would be affected by this, but we check for this // state here and fix the user if they are affected. // // We also fix the path in the case of the path not being quoted. size_t currentServicePathLen = wcslen(currentServicePath); bool doesServiceHaveCorrectPath = currentServicePathLen > 2 && !wcsstr(currentServicePath, L"maintenanceservice_tmp.exe") && currentServicePath[0] == L'\"' && currentServicePath[currentServicePathLen - 1] == L'\"'; if (doesServiceHaveCorrectPath) { LOG(("The MozillaMaintenance service path is correct.")); servicePathWasWrong = FALSE; return TRUE; } // This is a recoverable situation so not logging as a warning LOG(("The MozillaMaintenance path is NOT correct. It was: %ls", currentServicePath)); servicePathWasWrong = TRUE; WCHAR fixedPath[MAX_PATH + 1] = { L'\0' }; wcsncpy(fixedPath, currentServicePath, MAX_PATH); PathUnquoteSpacesW(fixedPath); if (!PathRemoveFileSpecW(fixedPath)) { LOG_WARN(("Couldn't remove file spec. (%d)", GetLastError())); return FALSE; } if (!PathAppendSafe(fixedPath, L"maintenanceservice.exe")) { LOG_WARN(("Couldn't append file spec. (%d)", GetLastError())); return FALSE; } PathQuoteSpacesW(fixedPath); if (!ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, fixedPath, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)) { LOG_WARN(("Could not fix service path. (%d)", GetLastError())); return FALSE; } LOG(("Fixed service path to: %ls.", fixedPath)); return TRUE; }
BOOL SetServiceConfig(LPQUERY_SERVICE_CONFIG pServiceConfig, LPWSTR lpServiceName, LPWSTR lpPassword) { SC_HANDLE hSCManager; SC_HANDLE hSc; SC_LOCK scLock; BOOL bRet = FALSE; hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK); if (hSCManager) { scLock = LockServiceDatabase(hSCManager); if (scLock) { hSc = OpenServiceW(hSCManager, lpServiceName, SERVICE_CHANGE_CONFIG); if (hSc) { if (ChangeServiceConfigW(hSc, pServiceConfig->dwServiceType, pServiceConfig->dwStartType, pServiceConfig->dwErrorControl, pServiceConfig->lpBinaryPathName, pServiceConfig->lpLoadOrderGroup, pServiceConfig->dwTagId ? &pServiceConfig->dwTagId : NULL, pServiceConfig->lpDependencies, pServiceConfig->lpServiceStartName, lpPassword, pServiceConfig->lpDisplayName)) { bRet = TRUE; } CloseServiceHandle(hSc); } UnlockServiceDatabase(scLock); } CloseServiceHandle(hSCManager); } if (!bRet) GetError(); return bRet; }
static BOOL EnableUserModePnpManager(VOID) { SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; BOOL bRet = FALSE; hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (hSCManager == NULL) { DPRINT1("Unable to open the service control manager.\n"); DPRINT1("Last Error %d\n", GetLastError()); goto cleanup; } hService = OpenServiceW(hSCManager, L"PlugPlay", SERVICE_CHANGE_CONFIG | SERVICE_START); if (hService == NULL) { DPRINT1("Unable to open PlugPlay service\n"); goto cleanup; } bRet = ChangeServiceConfigW(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (!bRet) { DPRINT1("Unable to change the service configuration\n"); goto cleanup; } bRet = StartServiceW(hService, 0, NULL); if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)) { DPRINT1("Unable to start service\n"); goto cleanup; } bRet = TRUE; cleanup: if (hService != NULL) CloseServiceHandle(hService); if (hSCManager != NULL) CloseServiceHandle(hSCManager); return bRet; }
/** * Determines if the MozillaMaintenance service path needs to be updated * and fixes it if it is wrong. * * @param service A handle to the service to fix. * @param currentServicePath The current (possibly wrong) path that is used. * @param servicePathWasWrong Out parameter set to TRUE if a fix was needed. * @return TRUE if the service path is now correct. */ BOOL FixServicePath(SC_HANDLE service, LPCWSTR currentServicePath, BOOL &servicePathWasWrong) { // When we originally upgraded the MozillaMaintenance service we // would uninstall the service on each upgrade. This had an // intermittent error which could cause the service to use the file // maintenanceservice_tmp.exe as the install path. Only a small number // of Nightly users would be affected by this, but we check for this // state here and fix the user if they are affected. bool doesServiceHaveCorrectPath = !wcsstr(currentServicePath, L"maintenanceservice_tmp.exe"); if (doesServiceHaveCorrectPath) { LOG(("The MozillaMaintenance service path is correct.\n")); servicePathWasWrong = FALSE; return TRUE; } LOG(("The MozillaMaintenance path is NOT correct.\n")); servicePathWasWrong = TRUE; WCHAR fixedPath[MAX_PATH + 1] = { L'\0' }; wcsncpy(fixedPath, currentServicePath, MAX_PATH); PathUnquoteSpacesW(fixedPath); if (!PathRemoveFileSpecW(fixedPath)) { LOG(("Couldn't remove file spec. (%d)\n", GetLastError())); return FALSE; } if (!PathAppendSafe(fixedPath, L"maintenanceservice.exe")) { LOG(("Couldn't append file spec. (%d)\n", GetLastError())); return FALSE; } PathQuoteSpacesW(fixedPath); if (!ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, fixedPath, NULL, NULL, NULL, NULL, NULL, NULL)) { LOG(("Could not fix service path. (%d)\n", GetLastError())); return FALSE; } LOG(("Fixed service path to: %ls.\n", fixedPath)); return TRUE; }
static VOID RpcSsConfigureAsNetworkService(VOID) { SC_HANDLE hSCManager, hService; /* Open the service controller */ hSCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); if (!hSCManager) { ERR("OpenSCManager() failed with error 0x%lx\n", GetLastError()); return; } /* Open the RPCSS service */ hService = OpenServiceW(hSCManager, L"RPCSS", SERVICE_CHANGE_CONFIG); if (!hService) ERR("OpenService(\"RPCSS\") failed with error 0x%lx\n", GetLastError()); if (hService) { /* Use the NetworkService account */ if (!ChangeServiceConfigW(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, L"NT AUTHORITY\\NetworkService", L"", NULL)) { ERR("ChangeServiceConfig(\"RPCSS\") failed with error 0x%lx\n", GetLastError()); } CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); }
void CSystemService::Install(LPCWSTR displayname) { WCHAR startcmd[MAX_PATH+5]; TCHAR filename[MAX_PATH]; if(0==::GetModuleFileName(nullptr,filename,MAX_PATH)) return; if(0==swprintf_s(startcmd,L"\"%s\" -s",filename))return; SC_HANDLE newService=nullptr, scm=nullptr; SERVICE_STATUS status; __try { scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); if (!scm) __leave; // Install the new service newService = OpenServiceW(scm,ServiceTable[0].lpServiceName,SERVICE_ALL_ACCESS); if(newService) { QUERY_SERVICE_CONFIG* querybuff=nullptr; DWORD bufsz=0; if(QueryServiceConfig(newService,querybuff,0,&bufsz)==FALSE) { if(ERROR_INSUFFICIENT_BUFFER==GetLastError()) { querybuff=(QUERY_SERVICE_CONFIG*)malloc(bufsz); if(querybuff) { if(QueryServiceConfig(newService,querybuff,bufsz,&bufsz)) { wchar_t* firstQuotes=nullptr,*secondQuotes=nullptr; firstQuotes=wcschr(querybuff->lpBinaryPathName,'"'); if(firstQuotes) { secondQuotes=wcschr(firstQuotes+1,'"'); if(secondQuotes) { wchar_t tempfilename[MAX_PATH]; wcsncpy_s(tempfilename,firstQuotes+1,secondQuotes-firstQuotes-1); if(_wcsicmp(tempfilename,filename)!=0) { if(StopService(newService)) { if(CopyFile(filename,tempfilename,FALSE)) { wcscpy_s(startcmd,querybuff->lpBinaryPathName); } } } } } } free(querybuff); } } } if(!ChangeServiceConfigW(newService, SERVICE_WIN32_SHARE_PROCESS|SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, startcmd, 0,0,dependens,0,0,0)) __leave; } else { newService = CreateServiceW( scm, ServiceTable[0].lpServiceName, displayname?displayname:ServiceTable[0].lpServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_SHARE_PROCESS|SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, startcmd, 0, 0, dependens, 0, 0); } if (newService) { SERVICE_FAILURE_ACTIONS sfa; ZeroMemory(&sfa,sizeof(sfa)); sfa.dwResetPeriod=INFINITE; sfa.cActions=3; SC_ACTION sact[3]; ZeroMemory(sact,sizeof(sact)); sfa.lpsaActions=sact; sact[0].Delay=500; sact[0].Type=SC_ACTION_RESTART; sact[1].Delay=500; sact[1].Type=SC_ACTION_RESTART; sact[2].Delay=500; sact[2].Type=SC_ACTION_RESTART; ChangeServiceConfig2(newService,SERVICE_CONFIG_FAILURE_ACTIONS,&sfa); if(QueryServiceStatus(newService,&status)) { if(status.dwCurrentState==SERVICE_STOPPED) { StartService(newService,0,0); } } } } __finally { if(newService)CloseServiceHandle(newService); if(scm)CloseServiceHandle(scm); } }
static void Test_LockUnlockServiceDatabaseWithServiceStart(void) { BOOL bError = FALSE; SC_HANDLE hScm = NULL; SC_HANDLE hSvc = NULL; SC_LOCK hLock = NULL; LPQUERY_SERVICE_CONFIGW lpConfig = NULL; DWORD dwRequiredSize = 0; SERVICE_STATUS status; BOOL bWasRunning = FALSE; DWORD dwOldStartType = 0; /* Open the services database */ SetLastError(0xdeadbeef); hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK); ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError()); if (!hScm) { skip("No service control manager; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n"); goto cleanup; } ok_err(ERROR_SUCCESS); /* Grab a handle to the testing service */ SetLastError(0xdeadbeef); hSvc = OpenServiceW(hScm, TESTING_SERVICE, SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS); ok(hSvc != NULL, "hSvc = 0x%p, expected non-null, error=0x%08lx\n", hSvc, GetLastError()); if (!hSvc) { skip("Cannot open a handle to service %S; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n", TESTING_SERVICE); goto cleanup; } ok_err(ERROR_SUCCESS); /* Lock the services database */ SetLastError(0xdeadbeef); hLock = LockServiceDatabase(hScm); ok(hLock != NULL, "hLock = 0x%p, expected non-zero, error=0x%08lx\n", hLock, GetLastError()); if (!hLock) { skip("Cannot lock the services database; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n"); goto cleanup; } ok_err(ERROR_SUCCESS); /* To proceed further, firstly attempt to stop the testing service */ QueryServiceConfigW(hSvc, NULL, 0, &dwRequiredSize); lpConfig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize); QueryServiceConfigW(hSvc, lpConfig, dwRequiredSize, &dwRequiredSize); dwOldStartType = lpConfig->dwStartType; HeapFree(GetProcessHeap(), 0, lpConfig); if (dwOldStartType == SERVICE_DISABLED) { ChangeServiceConfigW(hSvc, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } QueryServiceStatus(hSvc, &status); bWasRunning = (status.dwCurrentState != SERVICE_STOPPED); if (bWasRunning) { ControlService(hSvc, SERVICE_CONTROL_STOP, &status); Sleep(1000); /* Wait 1 second for the service to stop */ } /* Now try to start it (this test won't work under Windows Vista / 7 / 8) */ SetLastError(0xdeadbeef); bError = StartServiceW(hSvc, 0, NULL); ok(bError == FALSE, "bError = %u, expected FALSE\n", bError); ok_err(ERROR_SERVICE_DATABASE_LOCKED); Sleep(1000); /* Wait 1 second for the service to start */ /* Stop the testing service */ ControlService(hSvc, SERVICE_CONTROL_STOP, &status); Sleep(1000); /* Wait 1 second for the service to stop */ /* Now unlock the services database */ SetLastError(0xdeadbeef); bError = UnlockServiceDatabase(hLock); ok(bError == TRUE, "bError = %u, expected TRUE\n", bError); ok_err(ERROR_SUCCESS); /* Try to start again the service, this time the database unlocked */ SetLastError(0xdeadbeef); bError = StartServiceW(hSvc, 0, NULL); ok(bError == TRUE, "bError = %u, expected TRUE\n", bError); ok_err(ERROR_SUCCESS); Sleep(1000); /* Wait 1 second for the service to start */ /* Stop the testing service */ ControlService(hSvc, SERVICE_CONTROL_STOP, &status); Sleep(1000); /* Wait 1 second for the service to stop */ /* Restore its original state */ if (bWasRunning) { StartServiceW(hSvc, 0, NULL); } if (dwOldStartType == SERVICE_DISABLED) { ChangeServiceConfigW(hSvc, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } cleanup: if (hSvc) CloseServiceHandle(hSvc); if (hScm) CloseServiceHandle(hScm); return; }
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); Update_Btn_States(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 bAreThereModifs = FALSE; int index = -1; // From the beginning. while ((index = ListView_GetNextItem(hServicesListCtrl, index, LVNI_ALL)) != -1) { bAreThereModifs = ValidateItem(index, TRUE, FALSE) || bAreThereModifs; // The order is verrrrrry important !!!! } if (bAreThereModifs) { Update_Btn_States(hDlg); PropSheet_Changed(GetParent(hServicesPage), hServicesPage); } return TRUE; } case IDC_BTN_SERVICES_DEACTIVATE: { BOOL bAreThereModifs = FALSE; int index = -1; // From the beginning. while ((index = ListView_GetNextItem(hServicesListCtrl, index, LVNI_ALL)) != -1) { bAreThereModifs = ValidateItem(index, FALSE, FALSE) || bAreThereModifs; // The order is verrrrrry important !!!! } if (bAreThereModifs) { Update_Btn_States(hDlg); PropSheet_Changed(GetParent(hServicesPage), hServicesPage); } return TRUE; } case IDC_CBX_SERVICES_MASK_PROPRIETARY_SVCS: { bMaskProprietarySvcs = !bMaskProprietarySvcs; GetServices(bMaskProprietarySvcs); Update_Btn_States(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())) { Update_Btn_States(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- Retrive 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); Update_Btn_States(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; }