Severity: Warning
File: src/Servy.Core/Services/ServiceManager.cs:543-635
Code:
```csharp
// Line 560 — handle opened with stop/query/delete only
uint uninstallRights = SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_DELETE;
using (var serviceHandle = _windowsServiceApi.OpenService(scmHandle, serviceName, uninstallRights))
{
...
// Line 569-580 — but this requires SERVICE_CHANGE_CONFIG
// Standardize start type before stopping
_windowsServiceApi.ChangeServiceConfig(
serviceHandle,
SERVICE_NO_CHANGE,
SERVICE_DEMAND_START,
SERVICE_NO_CHANGE,
null, null, IntPtr.Zero,
null, null, null, null);
```
Explanation:
The Win32 `ChangeServiceConfig` API requires the `SERVICE_CHANGE_CONFIG` (0x0002) access right on the service handle. `UninstallServiceAsync` opens the handle with `SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_DELETE` only — `SERVICE_CHANGE_CONFIG` is missing. The call therefore fails with ERROR_ACCESS_DENIED at runtime, but the return value is also ignored, so the failure is silent. The intent of "standardize start type to demand-start before stopping" never actually takes effect; if the service was Automatic, it stays Automatic until it is finally deleted.
Suggested fix:
Add `SERVICE_CHANGE_CONFIG` to the requested access mask, and check the result:
```csharp
uint uninstallRights = SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_DELETE | SERVICE_CHANGE_CONFIG;
...
bool ok = _windowsServiceApi.ChangeServiceConfig(...);
if (!ok)
{
Logger.Warn($"Failed to standardize start type before uninstall for '{serviceName}': Win32 error {_win32ErrorProvider.GetLastWin32Error()}");
}
```
Severity: Warning
File: src/Servy.Core/Services/ServiceManager.cs:543-635
Code:
```csharp
// Line 560 — handle opened with stop/query/delete only
uint uninstallRights = SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_DELETE;
using (var serviceHandle = _windowsServiceApi.OpenService(scmHandle, serviceName, uninstallRights))
{
...
```
Explanation:
The Win32 `ChangeServiceConfig` API requires the `SERVICE_CHANGE_CONFIG` (0x0002) access right on the service handle. `UninstallServiceAsync` opens the handle with `SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_DELETE` only — `SERVICE_CHANGE_CONFIG` is missing. The call therefore fails with ERROR_ACCESS_DENIED at runtime, but the return value is also ignored, so the failure is silent. The intent of "standardize start type to demand-start before stopping" never actually takes effect; if the service was Automatic, it stays Automatic until it is finally deleted.
Suggested fix:
Add `SERVICE_CHANGE_CONFIG` to the requested access mask, and check the result:
```csharp
uint uninstallRights = SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_DELETE | SERVICE_CHANGE_CONFIG;
...
bool ok = _windowsServiceApi.ChangeServiceConfig(...);
if (!ok)
{
Logger.Warn($"Failed to standardize start type before uninstall for '{serviceName}': Win32 error {_win32ErrorProvider.GetLastWin32Error()}");
}
```