summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostDrivers/VBoxUSB/win/cmn
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostDrivers/VBoxUSB/win/cmn')
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/win/cmn/Makefile.kup0
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.cpp247
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.h113
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbIdc.h95
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.cpp428
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.h89
6 files changed, 972 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/VBoxUSB/win/cmn/Makefile.kup b/src/VBox/HostDrivers/VBoxUSB/win/cmn/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/win/cmn/Makefile.kup
diff --git a/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.cpp b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.cpp
new file mode 100644
index 00000000..63ed595b
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.cpp
@@ -0,0 +1,247 @@
+/* $Id: VBoxDrvTool.cpp $ */
+/** @file
+ * Windows Driver R0 Tooling.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include "VBoxDrvTool.h"
+
+#include <iprt/assert.h>
+#include <VBox/log.h>
+
+#include "../../../win/VBoxDbgLog.h"
+
+#define VBOXDRVTOOL_MEMTAG 'TDBV'
+
+static PVOID vboxDrvToolMemAlloc(SIZE_T cbBytes)
+{
+ PVOID pvMem = ExAllocatePoolWithTag(NonPagedPool, cbBytes, VBOXDRVTOOL_MEMTAG);
+ Assert(pvMem);
+ return pvMem;
+}
+
+static PVOID vboxDrvToolMemAllocZ(SIZE_T cbBytes)
+{
+ PVOID pvMem = vboxDrvToolMemAlloc(cbBytes);
+ if (pvMem)
+ {
+ RtlZeroMemory(pvMem, cbBytes);
+ }
+ return pvMem;
+}
+
+static VOID vboxDrvToolMemFree(PVOID pvMem)
+{
+ ExFreePoolWithTag(pvMem, VBOXDRVTOOL_MEMTAG);
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKeyU(OUT PHANDLE phKey, IN PUNICODE_STRING pName, IN ACCESS_MASK fAccess)
+{
+ OBJECT_ATTRIBUTES ObjAttr;
+
+ InitializeObjectAttributes(&ObjAttr, pName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
+
+ return ZwOpenKey(phKey, fAccess, &ObjAttr);
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
+{
+ UNICODE_STRING RtlStr;
+ RtlInitUnicodeString(&RtlStr, pName);
+
+ return VBoxDrvToolRegOpenKeyU(phKey, &RtlStr, fAccess);
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegCloseKey(IN HANDLE hKey)
+{
+ return ZwClose(hKey);
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PULONG pDword)
+{
+ struct
+ {
+ KEY_VALUE_PARTIAL_INFORMATION Info;
+ UCHAR Buf[32]; /* should be enough */
+ } Buf;
+ ULONG cbBuf;
+ UNICODE_STRING RtlStr;
+ RtlInitUnicodeString(&RtlStr, pName);
+ NTSTATUS Status = ZwQueryValueKey(hKey,
+ &RtlStr,
+ KeyValuePartialInformation,
+ &Buf.Info,
+ sizeof(Buf),
+ &cbBuf);
+ if (Status == STATUS_SUCCESS)
+ {
+ if (Buf.Info.Type == REG_DWORD)
+ {
+ Assert(Buf.Info.DataLength == 4);
+ *pDword = *((PULONG)Buf.Info.Data);
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_PARAMETER;
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT ULONG val)
+{
+ UNICODE_STRING RtlStr;
+ RtlInitUnicodeString(&RtlStr, pName);
+ return ZwSetValueKey(hKey, &RtlStr,
+ NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
+ REG_DWORD,
+ &val,
+ sizeof(val));
+}
+
+static NTSTATUS vboxDrvToolIoCompletionSetEvent(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pvContext)
+{
+ RT_NOREF2(pDevObj, pIrp);
+ PKEVENT pEvent = (PKEVENT)pvContext;
+ KeSetEvent(pEvent, 0, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostAsync(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent)
+{
+ IoSetCompletionRoutine(pIrp, vboxDrvToolIoCompletionSetEvent, pEvent, TRUE, TRUE, TRUE);
+ return IoCallDriver(pDevObj, pIrp);
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSync(PDEVICE_OBJECT pDevObj, PIRP pIrp)
+{
+ KEVENT Event;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ NTSTATUS Status = VBoxDrvToolIoPostAsync(pDevObj, pIrp, &Event);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = pIrp->IoStatus.Status;
+ }
+ return Status;
+}
+
+/* !!!NOTE: the caller MUST be the IRP owner!!! *
+ * !! one can not post threaded IRPs this way!! */
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSyncWithTimeout(PDEVICE_OBJECT pDevObj, PIRP pIrp, ULONG dwTimeoutMs)
+{
+ KEVENT Event;
+ LOG(("post irp (0x%p) to DevObj(0x%p) with timeout (%u)", pIrp, pDevObj, dwTimeoutMs));
+
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ NTSTATUS Status = VBoxDrvToolIoPostAsync(pDevObj, pIrp, &Event);
+ if (Status == STATUS_PENDING)
+ {
+ LARGE_INTEGER Interval;
+ PLARGE_INTEGER pInterval = NULL;
+ if (dwTimeoutMs != RT_INDEFINITE_WAIT)
+ {
+ Interval.QuadPart = -(int64_t) dwTimeoutMs /* ms */ * 10000;
+ pInterval = &Interval;
+ }
+
+ Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, pInterval);
+ if (Status == STATUS_TIMEOUT)
+ {
+ WARN(("irp (0x%p) to DevObj(0x%p) was not completed within timeout (%u), cancelling", pIrp, pDevObj, dwTimeoutMs));
+ if (!IoCancelIrp(pIrp))
+ {
+ /* this may happen, but this is something the caller with timeout is not expecting */
+ WARN(("IoCancelIrp failed"));
+ }
+
+ /* wait for the IRP to complete */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ }
+ else
+ {
+ ASSERT_WARN(Status == STATUS_SUCCESS, ("uunexpected Status (0x%x)", Status));
+ }
+
+ /* by this time the IRP is completed */
+ Status = pIrp->IoStatus.Status;
+ LOG(("Pending IRP(0x%p) completed with status(0x%x)", pIrp, Status));
+ }
+ else
+ {
+ LOG(("IRP(0x%p) completed with status(0x%x)", pIrp, Status));
+ }
+ return Status;
+}
+
+VBOXDRVTOOL_DECL(VOID) VBoxDrvToolRefWaitEqual(PVBOXDRVTOOL_REF pRef, uint32_t u32Val)
+{
+ LARGE_INTEGER Interval;
+ Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
+ uint32_t cRefs;
+ size_t loops = 0;
+ KTIMER kTimer;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ KeInitializeTimer(&kTimer);
+
+ while ((cRefs = ASMAtomicReadU32(&pRef->cRefs)) > u32Val && loops < 256)
+ {
+ Assert(cRefs >= u32Val);
+ Assert(cRefs < UINT32_MAX/2);
+
+ KeSetTimer(&kTimer, Interval, NULL);
+ status = KeWaitForSingleObject(&kTimer, Executive, KernelMode, false, NULL);
+ Assert(NT_SUCCESS(status));
+ loops++;
+ }
+}
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolStrCopy(PUNICODE_STRING pDst, CONST PUNICODE_STRING pSrc)
+{
+ USHORT cbLength = pSrc->Length + sizeof (pDst->Buffer[0]);
+ pDst->Buffer = (PWCHAR)vboxDrvToolMemAlloc(cbLength);
+ Assert(pDst->Buffer);
+ if (pDst->Buffer)
+ {
+ RtlMoveMemory(pDst->Buffer, pSrc->Buffer, pSrc->Length);
+ pDst->Buffer[pSrc->Length / sizeof (pDst->Buffer[0])] = L'\0';
+ pDst->Length = pSrc->Length;
+ pDst->MaximumLength = cbLength;
+ return STATUS_SUCCESS;
+ }
+ return STATUS_NO_MEMORY;
+}
+
+VBOXDRVTOOL_DECL(VOID) VBoxDrvToolStrFree(PUNICODE_STRING pStr)
+{
+ vboxDrvToolMemFree(pStr->Buffer);
+}
diff --git a/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.h b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.h
new file mode 100644
index 00000000..f953f8eb
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.h
@@ -0,0 +1,113 @@
+/* $Id: VBoxDrvTool.h $ */
+/** @file
+ * Windows Driver R0 Tooling.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxDrvTool_h
+#define VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxDrvTool_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <iprt/stdint.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/nt/wdm.h>
+
+
+RT_C_DECLS_BEGIN
+
+#if 0
+/* enable this in case we include this in a dll*/
+# ifdef IN_VBOXDRVTOOL
+# define VBOXDRVTOOL_DECL(a_Type) DECLEXPORT(a_Type)
+# else
+# define VBOXDRVTOOL_DECL(a_Type) DECLIMPORT(a_Type)
+# endif
+#else
+/*enable this in case we include this in a static lib*/
+# define VBOXDRVTOOL_DECL(a_Type) a_Type VBOXCALL
+#endif
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKeyU(OUT PHANDLE phKey, IN PUNICODE_STRING pName, IN ACCESS_MASK fAccess);
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess);
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegCloseKey(IN HANDLE hKey);
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PULONG pDword);
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT ULONG val);
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostAsync(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent);
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSync(PDEVICE_OBJECT pDevObj, PIRP pIrp);
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSyncWithTimeout(PDEVICE_OBJECT pDevObj, PIRP pIrp, ULONG dwTimeoutMs);
+DECLINLINE(NTSTATUS) VBoxDrvToolIoComplete(PIRP pIrp, NTSTATUS Status, ULONG ulInfo)
+{
+ pIrp->IoStatus.Status = Status;
+ pIrp->IoStatus.Information = ulInfo;
+ IoCompleteRequest(pIrp, IO_NO_INCREMENT);
+ return Status;
+}
+
+typedef struct VBOXDRVTOOL_REF
+{
+ volatile uint32_t cRefs;
+} VBOXDRVTOOL_REF, *PVBOXDRVTOOL_REF;
+
+DECLINLINE(void) VBoxDrvToolRefInit(PVBOXDRVTOOL_REF pRef)
+{
+ pRef->cRefs = 1;
+}
+
+DECLINLINE(uint32_t) VBoxDrvToolRefRetain(PVBOXDRVTOOL_REF pRef)
+{
+ Assert(pRef->cRefs);
+ Assert(pRef->cRefs < UINT32_MAX / 2);
+ return ASMAtomicIncU32(&pRef->cRefs);
+}
+
+DECLINLINE(uint32_t) VBoxDrvToolRefRelease(PVBOXDRVTOOL_REF pRef)
+{
+ uint32_t cRefs = ASMAtomicDecU32(&pRef->cRefs);
+ Assert(cRefs < UINT32_MAX/2);
+ return cRefs;
+}
+
+VBOXDRVTOOL_DECL(VOID) VBoxDrvToolRefWaitEqual(PVBOXDRVTOOL_REF pRef, uint32_t u32Val);
+
+VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolStrCopy(PUNICODE_STRING pDst, CONST PUNICODE_STRING pSrc);
+VBOXDRVTOOL_DECL(VOID) VBoxDrvToolStrFree(PUNICODE_STRING pStr);
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxDrvTool_h */
+
diff --git a/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbIdc.h b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbIdc.h
new file mode 100644
index 00000000..9bc69afb
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbIdc.h
@@ -0,0 +1,95 @@
+/* $Id: VBoxUsbIdc.h $ */
+/** @file
+ * Windows USB Proxy - Monitor Driver communication interface.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxUsbIdc_h
+#define VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxUsbIdc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#define VBOXUSBIDC_VERSION_MAJOR 1
+#define VBOXUSBIDC_VERSION_MINOR 0
+
+#define VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x618, METHOD_NEITHER, FILE_WRITE_ACCESS)
+#define VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x619, METHOD_NEITHER, FILE_WRITE_ACCESS)
+#define VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x61A, METHOD_NEITHER, FILE_WRITE_ACCESS)
+#define VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STATE_CHANGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x61B, METHOD_NEITHER, FILE_WRITE_ACCESS)
+
+typedef struct
+{
+ uint32_t u32Major;
+ uint32_t u32Minor;
+} VBOXUSBIDC_VERSION, *PVBOXUSBIDC_VERSION;
+
+typedef void *HVBOXUSBIDCDEV;
+
+/* the initial device state is USBDEVICESTATE_HELD_BY_PROXY */
+typedef struct VBOXUSBIDC_PROXY_STARTUP
+{
+ union
+ {
+ /* in: device PDO */
+ PDEVICE_OBJECT pPDO;
+ /* out: device handle to be used for subsequent USBSUP_PROXY_XXX calls */
+ HVBOXUSBIDCDEV hDev;
+ } u;
+} VBOXUSBIDC_PROXY_STARTUP, *PVBOXUSBIDC_PROXY_STARTUP;
+
+typedef struct VBOXUSBIDC_PROXY_TEARDOWN
+{
+ HVBOXUSBIDCDEV hDev;
+} VBOXUSBIDC_PROXY_TEARDOWN, *PVBOXUSBIDC_PROXY_TEARDOWN;
+
+typedef enum
+{
+ VBOXUSBIDC_PROXY_STATE_UNKNOWN = 0,
+ VBOXUSBIDC_PROXY_STATE_IDLE,
+ VBOXUSBIDC_PROXY_STATE_INITIAL = VBOXUSBIDC_PROXY_STATE_IDLE,
+ VBOXUSBIDC_PROXY_STATE_USED_BY_GUEST
+} VBOXUSBIDC_PROXY_STATE;
+
+typedef struct VBOXUSBIDC_PROXY_STATE_CHANGE
+{
+ HVBOXUSBIDCDEV hDev;
+ VBOXUSBIDC_PROXY_STATE enmState;
+} VBOXUSBIDC_PROXY_STATE_CHANGE, *PVBOXUSBIDC_PROXY_STATE_CHANGE;
+
+NTSTATUS VBoxUsbIdcInit();
+VOID VBoxUsbIdcTerm();
+NTSTATUS VBoxUsbIdcProxyStarted(PDEVICE_OBJECT pPDO, HVBOXUSBIDCDEV *phDev);
+NTSTATUS VBoxUsbIdcProxyStopped(HVBOXUSBIDCDEV hDev);
+
+#endif /* !VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxUsbIdc_h */
diff --git a/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.cpp b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.cpp
new file mode 100644
index 00000000..67383ea0
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.cpp
@@ -0,0 +1,428 @@
+/* $Id: VBoxUsbTool.cpp $ */
+/** @file
+ * Windows USB R0 Tooling.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#define INITGUID
+#include "VBoxUsbTool.h"
+#include <usbbusif.h>
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/utf16.h>
+#include <VBox/log.h>
+#include <VBox/usblib.h>
+
+#include "../../../win/VBoxDbgLog.h"
+
+#define VBOXUSBTOOL_MEMTAG 'TUBV'
+
+static PVOID vboxUsbToolMemAlloc(SIZE_T cbBytes)
+{
+ PVOID pvMem = ExAllocatePoolWithTag(NonPagedPool, cbBytes, VBOXUSBTOOL_MEMTAG);
+ Assert(pvMem);
+ return pvMem;
+}
+
+static PVOID vboxUsbToolMemAllocZ(SIZE_T cbBytes)
+{
+ PVOID pvMem = vboxUsbToolMemAlloc(cbBytes);
+ if (pvMem)
+ {
+ RtlZeroMemory(pvMem, cbBytes);
+ }
+ return pvMem;
+}
+
+static VOID vboxUsbToolMemFree(PVOID pvMem)
+{
+ ExFreePoolWithTag(pvMem, VBOXUSBTOOL_MEMTAG);
+}
+
+VBOXUSBTOOL_DECL(PURB) VBoxUsbToolUrbAlloc(USHORT u16Function, USHORT cbSize)
+{
+ PURB pUrb = (PURB)vboxUsbToolMemAlloc(cbSize);
+ Assert(pUrb);
+ if (!pUrb)
+ return NULL;
+
+ pUrb->UrbHeader.Length = cbSize;
+ pUrb->UrbHeader.Function = u16Function;
+ return pUrb;
+}
+
+VBOXUSBTOOL_DECL(PURB) VBoxUsbToolUrbAllocZ(USHORT u16Function, USHORT cbSize)
+{
+ PURB pUrb = (PURB)vboxUsbToolMemAllocZ(cbSize);
+ Assert(pUrb);
+ if (!pUrb)
+ return NULL;
+
+ pUrb->UrbHeader.Length = cbSize;
+ pUrb->UrbHeader.Function = u16Function;
+ return pUrb;
+}
+
+VBOXUSBTOOL_DECL(PURB) VBoxUsbToolUrbReinit(PURB pUrb, USHORT cbSize, USHORT u16Function)
+{
+ Assert(pUrb->UrbHeader.Length == cbSize);
+ if (pUrb->UrbHeader.Length < cbSize)
+ return NULL;
+ pUrb->UrbHeader.Length = cbSize;
+ pUrb->UrbHeader.Function = u16Function;
+ return pUrb;
+}
+
+VBOXUSBTOOL_DECL(VOID) VBoxUsbToolUrbFree(PURB pUrb)
+{
+ vboxUsbToolMemFree(pUrb);
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolUrbPost(PDEVICE_OBJECT pDevObj, PURB pUrb, ULONG dwTimeoutMs)
+{
+ if (dwTimeoutMs == RT_INDEFINITE_WAIT)
+ return VBoxUsbToolIoInternalCtlSendSync(pDevObj, IOCTL_INTERNAL_USB_SUBMIT_URB, pUrb, NULL);
+ return VBoxUsbToolIoInternalCtlSendSyncWithTimeout(pDevObj, IOCTL_INTERNAL_USB_SUBMIT_URB, pUrb, NULL, dwTimeoutMs);
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetDescriptor(PDEVICE_OBJECT pDevObj, void *pvBuffer, int cbBuffer, int Type, int iIndex, int LangId, ULONG dwTimeoutMs)
+{
+ NTSTATUS Status;
+ USHORT cbUrb = sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST);
+ PURB pUrb = VBoxUsbToolUrbAllocZ(URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, cbUrb);
+ if (!pUrb)
+ {
+ WARN(("allocating URB failed"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ PUSB_COMMON_DESCRIPTOR pCmn = (PUSB_COMMON_DESCRIPTOR)pvBuffer;
+ pCmn->bLength = cbBuffer;
+ pCmn->bDescriptorType = Type;
+
+ pUrb->UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
+ pUrb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
+ pUrb->UrbControlDescriptorRequest.TransferBufferLength = cbBuffer;
+ pUrb->UrbControlDescriptorRequest.TransferBuffer = pvBuffer;
+ pUrb->UrbControlDescriptorRequest.Index = (UCHAR)iIndex;
+ pUrb->UrbControlDescriptorRequest.DescriptorType = (UCHAR)Type;
+ pUrb->UrbControlDescriptorRequest.LanguageId = (USHORT)LangId;
+
+ Status = VBoxUsbToolUrbPost(pDevObj, pUrb, dwTimeoutMs);
+ ASSERT_WARN(Status == STATUS_SUCCESS, ("VBoxUsbToolUrbPost failed Status (0x%x)", Status));
+
+ VBoxUsbToolUrbFree(pUrb);
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(VOID) VBoxUsbToolStringDescriptorToUnicodeString(PUSB_STRING_DESCRIPTOR pDr, PUNICODE_STRING pUnicode)
+{
+ /* for some reason the string dr sometimes contains a non-null terminated string
+ * although we zeroed up the complete descriptor buffer
+ * this is why RtlInitUnicodeString won't work
+ * we need to init the scting length based on dr length */
+ pUnicode->Buffer = pDr->bString;
+ pUnicode->Length = pUnicode->MaximumLength = pDr->bLength - RT_OFFSETOF(USB_STRING_DESCRIPTOR, bString);
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetStringDescriptor(PDEVICE_OBJECT pDevObj, char *pszResult, ULONG cbResult,
+ int iIndex, int LangId, ULONG dwTimeoutMs)
+{
+ char aBuf[MAXIMUM_USB_STRING_LENGTH];
+ AssertCompile(sizeof (aBuf) <= UINT8_MAX);
+ UCHAR cbBuf = (UCHAR)sizeof (aBuf);
+ PUSB_STRING_DESCRIPTOR pDr = (PUSB_STRING_DESCRIPTOR)&aBuf;
+
+ Assert(pszResult);
+ *pszResult = 0;
+
+ memset(pDr, 0, cbBuf);
+ pDr->bLength = cbBuf;
+ pDr->bDescriptorType = USB_STRING_DESCRIPTOR_TYPE;
+
+ NTSTATUS Status = VBoxUsbToolGetDescriptor(pDevObj, pDr, cbBuf, USB_STRING_DESCRIPTOR_TYPE, iIndex, LangId, dwTimeoutMs);
+ if (NT_SUCCESS(Status))
+ {
+ if (pDr->bLength >= sizeof (USB_STRING_DESCRIPTOR))
+ {
+ int rc = RTUtf16ToUtf8Ex(pDr->bString, (pDr->bLength - RT_OFFSETOF(USB_STRING_DESCRIPTOR, bString)) / sizeof(RTUTF16),
+ &pszResult, cbResult, NULL /*pcch*/);
+ if (RT_SUCCESS(rc))
+ {
+ USBLibPurgeEncoding(pszResult);
+ Status = STATUS_SUCCESS;
+ }
+ else
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetLangID(PDEVICE_OBJECT pDevObj, int *pLangId, ULONG dwTimeoutMs)
+{
+ char aBuf[MAXIMUM_USB_STRING_LENGTH];
+ AssertCompile(sizeof (aBuf) <= UINT8_MAX);
+ UCHAR cbBuf = (UCHAR)sizeof (aBuf);
+ PUSB_STRING_DESCRIPTOR pDr = (PUSB_STRING_DESCRIPTOR)&aBuf;
+
+ Assert(pLangId);
+ *pLangId = 0;
+
+ memset(pDr, 0, cbBuf);
+ pDr->bLength = cbBuf;
+ pDr->bDescriptorType = USB_STRING_DESCRIPTOR_TYPE;
+
+ NTSTATUS Status = VBoxUsbToolGetDescriptor(pDevObj, pDr, cbBuf, USB_STRING_DESCRIPTOR_TYPE, 0, 0, dwTimeoutMs);
+ if (NT_SUCCESS(Status))
+ {
+ /* Just grab the first lang ID if available. In 99% cases, it will be US English (0x0409).*/
+ if (pDr->bLength >= sizeof (USB_STRING_DESCRIPTOR))
+ {
+ AssertCompile(sizeof (pDr->bString[0]) == sizeof (uint16_t));
+ *pLangId = pDr->bString[0];
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetDeviceSpeed(PDEVICE_OBJECT pDevObj, BOOLEAN *pbIsHigh)
+{
+ Assert(pbIsHigh);
+ *pbIsHigh = FALSE;
+
+ PIRP pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
+ Assert(pIrp);
+ if (!pIrp)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ USB_BUS_INTERFACE_USBDI_V1 BusIf;
+ PIO_STACK_LOCATION pSl = IoGetNextIrpStackLocation(pIrp);
+ pSl->MajorFunction = IRP_MJ_PNP;
+ pSl->MinorFunction = IRP_MN_QUERY_INTERFACE;
+ pSl->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_USBDI_GUID;
+ pSl->Parameters.QueryInterface.Size = sizeof (BusIf);
+ pSl->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_1;
+ pSl->Parameters.QueryInterface.Interface = (PINTERFACE)&BusIf;
+ pSl->Parameters.QueryInterface.InterfaceSpecificData = NULL;
+
+ pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+ NTSTATUS Status = VBoxDrvToolIoPostSync(pDevObj, pIrp);
+ Assert(NT_SUCCESS(Status) || Status == STATUS_NOT_SUPPORTED);
+ if (NT_SUCCESS(Status))
+ {
+ *pbIsHigh = BusIf.IsDeviceHighSpeed(BusIf.BusContext);
+ BusIf.InterfaceDereference(BusIf.BusContext);
+ }
+ IoFreeIrp(pIrp);
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolPipeClear(PDEVICE_OBJECT pDevObj, HANDLE hPipe, bool fReset)
+{
+ if (!hPipe)
+ {
+ Log(("Resetting the control pipe??\n"));
+ return STATUS_SUCCESS;
+ }
+ USHORT u16Function = fReset ? URB_FUNCTION_RESET_PIPE : URB_FUNCTION_ABORT_PIPE;
+ PURB pUrb = VBoxUsbToolUrbAlloc(u16Function, sizeof (struct _URB_PIPE_REQUEST));
+ if (!pUrb)
+ {
+ AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbAlloc failed!\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ pUrb->UrbPipeRequest.PipeHandle = hPipe;
+ pUrb->UrbPipeRequest.Reserved = 0;
+
+ NTSTATUS Status = VBoxUsbToolUrbPost(pDevObj, pUrb, RT_INDEFINITE_WAIT);
+ if (!NT_SUCCESS(Status) || !USBD_SUCCESS(pUrb->UrbHeader.Status))
+ {
+ AssertMsgFailed((__FUNCTION__": vboxUsbToolRequest failed with %x (%x)\n", Status, pUrb->UrbHeader.Status));
+ }
+
+ VBoxUsbToolUrbFree(pUrb);
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolCurrentFrame(PDEVICE_OBJECT pDevObj, PIRP pIrp, PULONG piFrame)
+{
+ struct _URB_GET_CURRENT_FRAME_NUMBER Urb;
+ Urb.Hdr.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER;
+ Urb.Hdr.Length = sizeof(Urb);
+ Urb.FrameNumber = (ULONG)-1;
+
+ Assert(piFrame);
+ *piFrame = (ULONG)-1;
+
+ PIO_STACK_LOCATION pSl = IoGetNextIrpStackLocation(pIrp);
+ pSl->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ pSl->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+ pSl->Parameters.Others.Argument1 = (PVOID)&Urb;
+ pSl->Parameters.Others.Argument2 = NULL;
+
+ NTSTATUS Status = VBoxUsbToolUrbPost(pDevObj, (PURB)&Urb, RT_INDEFINITE_WAIT);
+ Assert(NT_SUCCESS(Status));
+ if (NT_SUCCESS(Status))
+ {
+ *piFrame = Urb.FrameNumber;
+ }
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolDevUnconfigure(PDEVICE_OBJECT pDevObj)
+{
+ USHORT cbUrb = sizeof (struct _URB_SELECT_CONFIGURATION);
+ PURB pUrb = VBoxUsbToolUrbAlloc(URB_FUNCTION_SELECT_CONFIGURATION, cbUrb);
+ Assert(pUrb);
+ if (!pUrb)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ UsbBuildSelectConfigurationRequest(pUrb, (USHORT)cbUrb, NULL);
+
+ NTSTATUS Status = VBoxUsbToolUrbPost(pDevObj, pUrb, RT_INDEFINITE_WAIT);
+ Assert(NT_SUCCESS(Status));
+
+ VBoxUsbToolUrbFree(pUrb);
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(PIRP) VBoxUsbToolIoBuildAsyncInternalCtl(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2)
+{
+ PIRP pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE);
+ Assert(pIrp);
+ if (!pIrp)
+ {
+ return NULL;
+ }
+
+ pIrp->IoStatus.Status = STATUS_SUCCESS;
+ pIrp->IoStatus.Information = NULL;
+
+ PIO_STACK_LOCATION pSl = IoGetNextIrpStackLocation(pIrp);
+ pSl->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ pSl->MinorFunction = 0;
+ pSl->Parameters.DeviceIoControl.IoControlCode = uCtl;
+ pSl->Parameters.Others.Argument1 = pvArg1;
+ pSl->Parameters.Others.Argument2 = pvArg2;
+ return pIrp;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolIoInternalCtlSendSyncWithTimeout(PDEVICE_OBJECT pDevObj, ULONG uCtl,
+ void *pvArg1, void *pvArg2, ULONG dwTimeoutMs)
+{
+ /* since we're going to cancel the irp on timeout, we should allocate our own IRP rather than using the threaded one
+ * */
+ PIRP pIrp = VBoxUsbToolIoBuildAsyncInternalCtl(pDevObj, uCtl, pvArg1, pvArg2);
+ if (!pIrp)
+ {
+ WARN(("VBoxUsbToolIoBuildAsyncInternalCtl failed"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ NTSTATUS Status = VBoxDrvToolIoPostSyncWithTimeout(pDevObj, pIrp, dwTimeoutMs);
+
+ IoFreeIrp(pIrp);
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolIoInternalCtlSendAsync(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2,
+ PKEVENT pEvent, PIO_STATUS_BLOCK pIoStatus)
+{
+ NTSTATUS Status;
+ PIRP pIrp;
+ PIO_STACK_LOCATION pSl;
+ Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ pIrp = IoBuildDeviceIoControlRequest(uCtl, pDevObj, NULL, 0, NULL, 0, TRUE, pEvent, pIoStatus);
+ if (!pIrp)
+ {
+ WARN(("IoBuildDeviceIoControlRequest failed!!\n"));
+ pIoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;
+ pIoStatus->Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Get the next stack location as that is used for the new irp */
+ pSl = IoGetNextIrpStackLocation(pIrp);
+ pSl->Parameters.Others.Argument1 = pvArg1;
+ pSl->Parameters.Others.Argument2 = pvArg2;
+
+ Status = IoCallDriver(pDevObj, pIrp);
+
+ return Status;
+}
+
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolIoInternalCtlSendSync(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2)
+{
+ IO_STATUS_BLOCK IoStatus = {0};
+ KEVENT Event;
+ NTSTATUS Status;
+
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+ LOG(("Sending sync Ctl pDevObj(0x%p), uCtl(0x%x), pvArg1(0x%p), pvArg2(0x%p)", pDevObj, uCtl, pvArg1, pvArg2));
+
+ Status = VBoxUsbToolIoInternalCtlSendAsync(pDevObj, uCtl, pvArg1, pvArg2, &Event, &IoStatus);
+
+ if (Status == STATUS_PENDING)
+ {
+ LOG(("VBoxUsbToolIoInternalCtlSendAsync returned pending for pDevObj(0x%p)", pDevObj));
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = IoStatus.Status;
+ LOG(("Pending VBoxUsbToolIoInternalCtlSendAsync completed with Status (0x%x) for pDevObj(0x%p)", Status, pDevObj));
+ }
+ else
+ {
+ LOG(("VBoxUsbToolIoInternalCtlSendAsync completed with Status (0x%x) for pDevObj(0x%p)", Status, pDevObj));
+ }
+
+ return Status;
+}
diff --git a/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.h b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.h
new file mode 100644
index 00000000..e6c6c236
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxUsbTool.h
@@ -0,0 +1,89 @@
+/* $Id: VBoxUsbTool.h $ */
+/** @file
+ * Windows USB R0 Tooling.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxUsbTool_h
+#define VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxUsbTool_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxDrvTool.h"
+
+RT_C_DECLS_BEGIN
+#pragma warning( disable : 4200 )
+#include <usbdi.h>
+#pragma warning( default : 4200 )
+#include <usbdlib.h>
+
+RT_C_DECLS_END
+
+#if 0
+/* enable this in case we include this in a dll*/
+# ifdef IN_VBOXUSBTOOL
+# define VBOXUSBTOOL_DECL(a_Type) DECLEXPORT(a_Type)
+# else
+# define VBOXUSBTOOL_DECL(a_Type) DECLIMPORT(a_Type)
+# endif
+#else
+/*enable this in case we include this in a static lib*/
+# define VBOXUSBTOOL_DECL(a_Type) a_Type VBOXCALL
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+VBOXUSBTOOL_DECL(PURB) VBoxUsbToolUrbAlloc(USHORT u16Function, USHORT cbSize);
+VBOXUSBTOOL_DECL(PURB) VBoxUsbToolUrbAllocZ(USHORT u16Function, USHORT cbSize);
+VBOXUSBTOOL_DECL(PURB) VBoxUsbToolUrbReinit(PURB pUrb, USHORT cbSize, USHORT u16Function);
+VBOXUSBTOOL_DECL(VOID) VBoxUsbToolUrbFree(PURB pUrb);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolUrbPost(PDEVICE_OBJECT pDevObj, PURB pUrb, ULONG dwTimeoutMs);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetDescriptor(PDEVICE_OBJECT pDevObj, void *pvBuffer, int cbBuffer, int Type, int iIndex, int LangId, ULONG dwTimeoutMs);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetStringDescriptor(PDEVICE_OBJECT pDevObj, char *pszResult, ULONG cbResult, int iIndex, int LangId, ULONG dwTimeoutMs);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetLangID(PDEVICE_OBJECT pDevObj, int *pLangId, ULONG dwTimeoutMs);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetDeviceSpeed(PDEVICE_OBJECT pDevObj, BOOLEAN *pbIsHigh);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolPipeClear(PDEVICE_OBJECT pDevObj, HANDLE hPipe, bool fReset);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolCurrentFrame(PDEVICE_OBJECT pDevObj, PIRP pIrp, PULONG piFrame);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolDevUnconfigure(PDEVICE_OBJECT pDevObj);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolIoInternalCtlSendAsync(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2, PKEVENT pEvent, PIO_STATUS_BLOCK pIoStatus);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolIoInternalCtlSendSync(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2);
+VBOXUSBTOOL_DECL(PIRP) VBoxUsbToolIoBuildAsyncInternalCtl(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2);
+VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolIoInternalCtlSendSyncWithTimeout(PDEVICE_OBJECT pDevObj, ULONG uCtl, void *pvArg1, void *pvArg2, ULONG dwTimeoutMs);
+VBOXUSBTOOL_DECL(VOID) VBoxUsbToolStringDescriptorToUnicodeString(PUSB_STRING_DESCRIPTOR pDr, PUNICODE_STRING pUnicode);
+
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_SRC_VBoxUSB_win_cmn_VBoxUsbTool_h */