Refactor installer custom actions

This commit is contained in:
Frans van Dorsselaer committed 2025-09-13 16:35:21 +02:00
1 parent ec16b4c7ca
commit 9dc5195b25
6 files changed
+86 -67

No files matched your search

+15 -9
View File
@@ -94,17 +94,21 @@ SPDX-License-Identifier: GPL-3.0-only
</Component>
</DirectoryRef>
<!-- This will restore the original Windows drivers for devices that were forced bound. -->
<!-- This will restore the original Windows drivers for devices that were forced bound (best effort). -->
<SetProperty Id="UnbindAll" Value="&quot;[#usbipd.exe]&quot; unbind --all" Sequence="execute" Before="UnbindAll" Condition="(?usbipd.exe=3) AND ($usbipd.exe=2)" />
<CustomAction Id="UnbindAll" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Return="ignore" Impersonate="no" Execute="deferred" />
<!-- This will uninstall the drivers. -->
<SetProperty Id="UninstallDrivers" Value="&quot;[#usbipd.exe]&quot; uninstall" Sequence="execute" Before="UninstallDrivers" Condition="(?usbipd.exe=3) AND ($usbipd.exe=2)" />
<CustomAction Id="UninstallDrivers" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Return="ignore" Impersonate="no" Execute="deferred" />
<!-- This will uninstall the current VBoxUSB driver (best effort). -->
<SetProperty Id="UninstallDriver" Value="&quot;[#usbipd.exe]&quot; installer uninstall_driver" Sequence="execute" Before="UninstallDriver" Condition="(?usbipd.exe=3) AND ($usbipd.exe=2)" />
<CustomAction Id="UninstallDriver" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Return="ignore" Impersonate="no" Execute="deferred" />
<!-- This will install the drivers. -->
<SetProperty Id="InstallDrivers" Value="&quot;[#usbipd.exe]&quot; install" Sequence="execute" Before="InstallDrivers" Condition="$usbipd.exe=3" />
<CustomAction Id="InstallDrivers" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Return="check" Impersonate="no" Execute="deferred" />
<!-- This will install the VBoxUSB PnP driver (required). -->
<SetProperty Id="InstallDriver" Value="&quot;[#usbipd.exe]&quot; installer install_driver" Sequence="execute" Before="InstallDriver" Condition="$usbipd.exe=3" />
<CustomAction Id="InstallDriver" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Return="check" Impersonate="no" Execute="deferred" />
<!-- This will install VBoxUSBMon as a service (required). -->
<SetProperty Id="InstallMonitor" Value="&quot;[#usbipd.exe]&quot; installer install_monitor" Sequence="execute" Before="InstallMonitor" Condition="$usbipd.exe=3" />
<CustomAction Id="InstallMonitor" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Return="check" Impersonate="no" Execute="deferred" />
<!--
This will *try to* start the service. However, unlike ServiceControl, it will not fail if it can't.
@@ -119,9 +123,11 @@ SPDX-License-Identifier: GPL-3.0-only
<!-- NOTE: first make sure that no devices are using VBoxUSB, or else VBoxUSBMon does not stop -->
<Custom Action="UnbindAll" Before="StopServices" Condition="(?usbipd.exe=3) AND ($usbipd.exe=2)" />
<!-- Condition: usbipd.exe is installed and will be uninstalled -->
<Custom Action="UninstallDrivers" After="StopServices" Condition="(?usbipd.exe=3) AND ($usbipd.exe=2)" />
<Custom Action="UninstallDriver" After="StopServices" Condition="(?usbipd.exe=3) AND ($usbipd.exe=2)" />
<!-- Condition: usbipd.exe will be (or remains) installed -->
<Custom Action="InstallDrivers" Before="InstallServices" Condition="$usbipd.exe=3" />
<Custom Action="InstallDriver" Before="InstallServices" Condition="$usbipd.exe=3" />
<!-- Condition: usbipd.exe will be (or remains) installed -->
<Custom Action="InstallMonitor" Before="InstallServices" Condition="$usbipd.exe=3" />
<!-- Condition: usbipd.exe will be (or remains) installed -->
<Custom Action="TryStartService" After="StartServices" Condition="$usbipd.exe=3" />
</InstallExecuteSequence>
+38 -29
View File
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-3.0-only
using System.Runtime.InteropServices;
using System.ComponentModel;
using Windows.Win32;
using Windows.Win32.Devices.DeviceAndDriverInstallation;
using Windows.Win32.Foundation;
@@ -12,9 +12,9 @@ namespace Usbipd;
sealed partial class CommandHandlers : ICommandHandlers
{
Task<ExitCode> ICommandHandlers.Install(IConsole console, CancellationToken cancellationToken)
Task<ExitCode> ICommandHandlers.InstallerInstallDriver(IConsole console, CancellationToken cancellationToken)
{
ConsoleTools.ReportInfo(console, "install helper");
ConsoleTools.ReportInfo(console, "install_driver");
var path = Path.GetDirectoryName(Environment.ProcessPath)!;
ConsoleTools.ReportInfo(console, $"path = {path}");
@@ -27,41 +27,19 @@ sealed partial class CommandHandlers : ICommandHandlers
{
if (!PInvoke.SetupCopyOEMInf(inf, null, OEM_SOURCE_MEDIA_TYPE.SPOST_PATH, 0, null, 0))
{
console.ReportError($"SetupCopyOEMInf -> {Marshal.GetLastWin32Error()}");
console.ReportError($"SetupCopyOEMInf -> {new Win32Exception()}");
return Task.FromResult(ExitCode.Failure);
}
}
}
}
{
ConsoleTools.ReportInfo(console, $"Installing VBoxUSBMon");
// NOTE: This cannot be done from WiX, since WiX cannot create SERVICE_KERNEL_DRIVER; removal from WiX works though.
using var manager = PInvoke.OpenSCManager(string.Empty, PInvoke.SERVICES_ACTIVE_DATABASE, PInvoke.SC_MANAGER_ALL_ACCESS);
if (manager.IsInvalid)
{
console.ReportError($"OpenSCManager -> {Marshal.GetLastWin32Error()}");
return Task.FromResult(ExitCode.Failure);
}
unsafe // DevSkim: ignore DS172412
{
using var service = PInvoke.CreateService(manager, "VBoxUSBMon", "VirtualBox USB Monitor Service",
(uint)GENERIC_ACCESS_RIGHTS.GENERIC_ALL, ENUM_SERVICE_TYPE.SERVICE_KERNEL_DRIVER, SERVICE_START_TYPE.SERVICE_DEMAND_START,
SERVICE_ERROR.SERVICE_ERROR_NORMAL, Path.Combine(path, "Drivers", "VBoxUSBMon.sys"), null, null, null, null, null);
if (service.IsInvalid)
{
console.ReportError($"CreateService -> {Marshal.GetLastWin32Error()}");
return Task.FromResult(ExitCode.Failure);
}
}
}
return Task.FromResult(ExitCode.Success);
}
Task<ExitCode> ICommandHandlers.Uninstall(IConsole console, CancellationToken cancellationToken)
Task<ExitCode> ICommandHandlers.InstallerUninstallDriver(IConsole console, CancellationToken cancellationToken)
{
ConsoleTools.ReportInfo(console, $"uninstall helper");
ConsoleTools.ReportInfo(console, $"uninstall_driver");
var path = Path.GetDirectoryName(Environment.ProcessPath)!;
ConsoleTools.ReportInfo(console, $"path = {path}");
@@ -74,7 +52,7 @@ sealed partial class CommandHandlers : ICommandHandlers
BOOL needReboot;
if (!PInvoke.DiUninstallDriver(HWND.Null, Path.Combine(path, "Drivers", "VBoxUSB.inf"), 0, &needReboot))
{
console.ReportError($"DiUninstallDriver -> {Marshal.GetLastWin32Error()}");
console.ReportError($"DiUninstallDriver -> {new Win32Exception()}");
success = false;
// continue
}
@@ -84,4 +62,35 @@ sealed partial class CommandHandlers : ICommandHandlers
return Task.FromResult(success ? ExitCode.Success : ExitCode.Failure);
}
Task<ExitCode> ICommandHandlers.InstallerInstallMonitor(IConsole console, CancellationToken cancellationToken)
{
ConsoleTools.ReportInfo(console, "install_monitor");
var path = Path.GetDirectoryName(Environment.ProcessPath)!;
ConsoleTools.ReportInfo(console, $"path = {path}");
{
ConsoleTools.ReportInfo(console, $"Installing VBoxUSBMon");
// NOTE: This cannot be done from WiX, since WiX cannot create SERVICE_KERNEL_DRIVER; removal from WiX works though.
using var manager = PInvoke.OpenSCManager(string.Empty, PInvoke.SERVICES_ACTIVE_DATABASE, PInvoke.SC_MANAGER_ALL_ACCESS);
if (manager.IsInvalid)
{
console.ReportError($"OpenSCManager -> {new Win32Exception()}");
return Task.FromResult(ExitCode.Failure);
}
unsafe // DevSkim: ignore DS172412
{
using var service = PInvoke.CreateService(manager, "VBoxUSBMon", "VirtualBox USB Monitor Service",
(uint)GENERIC_ACCESS_RIGHTS.GENERIC_ALL, ENUM_SERVICE_TYPE.SERVICE_KERNEL_DRIVER, SERVICE_START_TYPE.SERVICE_DEMAND_START,
SERVICE_ERROR.SERVICE_ERROR_NORMAL, Path.Combine(path, "Drivers", "VBoxUSBMon.sys"), null, null, null, null, null);
if (service.IsInvalid)
{
console.ReportError($"CreateService -> {new Win32Exception()}");
return Task.FromResult(ExitCode.Failure);
}
}
}
return Task.FromResult(ExitCode.Success);
}
}
+2 -2
View File
@@ -68,7 +68,7 @@ sealed partial class DeviceFile : IDisposable
}
else
{
taskCompletionSource.SetException(new Win32Exception((int)errorCode, $"DeviceIoControl returned error {(WIN32_ERROR)errorCode}"));
taskCompletionSource.SetException(new Win32Exception((int)errorCode));
}
}
finally
@@ -83,7 +83,7 @@ sealed partial class DeviceFile : IDisposable
if (!PInvoke.DeviceIoControl(FileHandle, ioControlCode, pInput, (uint)(input?.Length ?? 0),
pOutput, (uint)(output?.Length ?? 0), null, nativeOverlapped))
{
var errorCode = (WIN32_ERROR)Marshal.GetLastWin32Error();
var errorCode = (WIN32_ERROR)Marshal.GetLastPInvokeError();
if (errorCode != WIN32_ERROR.ERROR_IO_PENDING)
{
OnCompletion((uint)errorCode, 0, nativeOverlapped);
+1 -1
View File
@@ -212,7 +212,7 @@ static class DriverTools
// This is a best-effort attempt; we ignore errors.
if (!PInvoke.DiUninstallDevice(default, usbDevices, devInfo, 0, &tmpReboot))
{
log.WriteLine($"Uninstall failed: {Marshal.GetLastPInvokeError()}: {Marshal.GetLastPInvokeErrorMessage()}");
log.WriteLine($"DiUninstallDevice -> {new Win32Exception()}");
}
else if (tmpReboot)
{
+14 -8
View File
@@ -9,6 +9,7 @@ namespace Usbipd;
interface ICommandHandlers
{
// CLI
Task<ExitCode> AttachWsl(BusId busId, bool autoAttach, bool unplugged, string? distribution, IPAddress? hostAddress,
IConsole console, CancellationToken cancellationToken);
Task<ExitCode> AttachWsl(VidPid vidPid, bool autoAttach, string? distribution, IPAddress? hostAddress,
@@ -20,16 +21,21 @@ interface ICommandHandlers
Task<ExitCode> DetachAll(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> License(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> List(bool usbIds, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Server(string[] args, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Unbind(BusId busId, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Unbind(Guid guid, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Unbind(VidPid vidPid, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> UnbindAll(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> State(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Install(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Uninstall(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> PolicyAdd(PolicyRule rule, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> PolicyList(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> PolicyRemove(Guid guid, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> PolicyRemoveAll(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> State(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Unbind(BusId busId, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Unbind(Guid guid, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> Unbind(VidPid vidPid, IConsole console, CancellationToken cancellationToken);
Task<ExitCode> UnbindAll(IConsole console, CancellationToken cancellationToken);
// Server
Task<ExitCode> Server(string[] args, IConsole console, CancellationToken cancellationToken);
// Installer
Task<ExitCode> InstallerInstallDriver(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> InstallerInstallMonitor(IConsole console, CancellationToken cancellationToken);
Task<ExitCode> InstallerUninstallDriver(IConsole console, CancellationToken cancellationToken);
}
+16 -18
View File
@@ -733,30 +733,28 @@ static class Program
}
{
//
// install
// installer
//
var installCommand = new Command("install")
var installCommand = new Command("installer")
{
Hidden = true,
};
installCommand.SetAction(async (parseResult, cancellationToken) => (int)
await commandHandlers.Install(console, cancellationToken)
);
void AddInstallerSubcommand(string name, Func<IConsole, CancellationToken, Task<ExitCode>> action)
{
var subcommand = new Command(name);
subcommand.SetAction(async (parseResult, cancellationToken) => (int)
await action(console, cancellationToken)
);
installCommand.Subcommands.Add(subcommand);
}
AddInstallerSubcommand("install_driver", commandHandlers.InstallerInstallDriver);
AddInstallerSubcommand("uninstall_driver", commandHandlers.InstallerUninstallDriver);
AddInstallerSubcommand("install_monitor", commandHandlers.InstallerInstallMonitor);
rootCommand.Subcommands.Add(installCommand);
}
{
//
// uninstall
//
var uninstallCommand = new Command("uninstall")
{
Hidden = true,
};
uninstallCommand.SetAction(async (parseResult, cancellationToken) => (int)
await commandHandlers.Uninstall(console, cancellationToken)
);
rootCommand.Subcommands.Add(uninstallCommand);
}
try
{