| 133 | } |
| 134 | |
| 135 | static std::wstring getServiceByDescription(const std::wstring& description) |
| 136 | { |
| 137 | SC_HANDLE hSCM = NULL; |
| 138 | LPENUM_SERVICE_STATUSW lpServices = NULL; |
| 139 | LPBYTE lpBuf = NULL; |
| 140 | DWORD cbBufSize = 0; |
| 141 | DWORD lpServicesReturned = 0; |
| 142 | DWORD pcbBytesNeeded = 0; |
| 143 | DWORD lpResumeHandle = 0;; |
| 144 | |
| 145 | if (l_Debug) |
| 146 | std::wcout << L"Opening SC Manager" << '\n'; |
| 147 | |
| 148 | hSCM = OpenSCManager(NULL, NULL, GENERIC_READ); |
| 149 | if (hSCM == NULL) |
| 150 | goto die; |
| 151 | |
| 152 | if (l_Debug) |
| 153 | std::wcout << L"Determining initially required memory" << '\n'; |
| 154 | |
| 155 | EnumServicesStatus(hSCM, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, NULL, 0, |
| 156 | &pcbBytesNeeded, &lpServicesReturned, &lpResumeHandle); |
| 157 | |
| 158 | /* This should always be ERROR_INSUFFICIENT_BUFFER... But for some reason it is sometimes ERROR_MORE_DATA |
| 159 | * See the MSDN on EnumServiceStatus for a glimpse of despair |
| 160 | */ |
| 161 | |
| 162 | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER && GetLastError() != ERROR_MORE_DATA) |
| 163 | goto die; |
| 164 | |
| 165 | lpServices = reinterpret_cast<LPENUM_SERVICE_STATUSW>(new BYTE[pcbBytesNeeded]); |
| 166 | |
| 167 | if (l_Debug) |
| 168 | std::wcout << L"Requesting Service Information. Entry point: " << lpResumeHandle << '\n'; |
| 169 | |
| 170 | EnumServicesStatus(hSCM, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, lpServices, pcbBytesNeeded, |
| 171 | &pcbBytesNeeded, &lpServicesReturned, &lpResumeHandle); |
| 172 | |
| 173 | for (decltype(lpServicesReturned) index = 0; index < lpServicesReturned; index++) { |
| 174 | LPWSTR lpCurrent = lpServices[index].lpServiceName; |
| 175 | |
| 176 | if (l_Debug) { |
| 177 | std::wcout << L"Opening Service \"" << lpServices[index].lpServiceName << L"\"\n"; |
| 178 | } |
| 179 | |
| 180 | SC_HANDLE hService = OpenService(hSCM, lpCurrent, SERVICE_QUERY_CONFIG); |
| 181 | if (!hService) |
| 182 | goto die; |
| 183 | |
| 184 | DWORD dwBytesNeeded = 0; |
| 185 | if (l_Debug) |
| 186 | std::wcout << "Accessing config\n"; |
| 187 | |
| 188 | if (!QueryServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) |
| 189 | continue; |
| 190 | |
| 191 | LPSERVICE_DESCRIPTION lpsd = reinterpret_cast<LPSERVICE_DESCRIPTION>(new BYTE[dwBytesNeeded]); |
| 192 |
no test coverage detected