mirror of
https://github.com/reactos/reactos.git
synced 2024-08-23 03:42:40 +00:00
![Johannes Anderwald](/assets/img/avatar_default.png)
- Null terminate buffer from IOCTL_USB_GET_ROOT_HUB_NAME, fixes usbview problems - Implement URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, IUSBHardware needs more work - Silence debug traces - Start implementing IUSBRequest interfaces - Complete unhandled major irp with status success svn path=/branches/usb-bringup/; revision=51396
753 lines
19 KiB
C++
753 lines
19 KiB
C++
/*
|
|
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: drivers/usb/usbehci/hcd_controller.cpp
|
|
* PURPOSE: USB EHCI device driver.
|
|
* PROGRAMMERS:
|
|
* Michael Martin (michael.martin@reactos.org)
|
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
*/
|
|
|
|
#define INITGUID
|
|
#include "usbehci.h"
|
|
|
|
class CHCDController : public IHCDController,
|
|
public IDispatchIrp
|
|
{
|
|
public:
|
|
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
|
|
|
|
STDMETHODIMP_(ULONG) AddRef()
|
|
{
|
|
InterlockedIncrement(&m_Ref);
|
|
return m_Ref;
|
|
}
|
|
STDMETHODIMP_(ULONG) Release()
|
|
{
|
|
InterlockedDecrement(&m_Ref);
|
|
|
|
if (!m_Ref)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_Ref;
|
|
}
|
|
|
|
// IHCDController interface functions
|
|
NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
|
|
|
|
// IDispatchIrp interface functions
|
|
NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
|
|
NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
|
|
NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
|
|
|
|
// local functions
|
|
NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
|
|
NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
|
|
NTSTATUS SetSymbolicLink(BOOLEAN Enable);
|
|
|
|
// constructor / destructor
|
|
CHCDController(IUnknown *OuterUnknown){}
|
|
virtual ~CHCDController(){}
|
|
|
|
protected:
|
|
LONG m_Ref;
|
|
PROOTHDCCONTROLLER m_RootController;
|
|
PDRIVER_OBJECT m_DriverObject;
|
|
PDEVICE_OBJECT m_PhysicalDeviceObject;
|
|
PDEVICE_OBJECT m_FunctionalDeviceObject;
|
|
PDEVICE_OBJECT m_NextDeviceObject;
|
|
PUSBHARDWAREDEVICE m_Hardware;
|
|
PHUBCONTROLLER m_HubController;
|
|
ULONG m_FDODeviceNumber;
|
|
};
|
|
|
|
//=================================================================================================
|
|
// COM
|
|
//
|
|
NTSTATUS
|
|
STDMETHODCALLTYPE
|
|
CHCDController::QueryInterface(
|
|
IN REFIID refiid,
|
|
OUT PVOID* Output)
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
NTSTATUS
|
|
CHCDController::Initialize(
|
|
IN PROOTHDCCONTROLLER RootHCDController,
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
|
{
|
|
NTSTATUS Status;
|
|
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
|
|
|
//
|
|
// create usb hardware
|
|
//
|
|
Status = CreateUSBHardware(&m_Hardware);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// failed to create hardware object
|
|
//
|
|
DPRINT1("Failed to create hardware object\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// initialize members
|
|
//
|
|
m_DriverObject = DriverObject;
|
|
m_PhysicalDeviceObject = PhysicalDeviceObject;
|
|
m_RootController = RootHCDController;
|
|
|
|
//
|
|
// create FDO
|
|
//
|
|
Status = CreateFDO(m_DriverObject, &m_FunctionalDeviceObject);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// failed to create PDO
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// now attach to device stack
|
|
//
|
|
m_NextDeviceObject = IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject, m_PhysicalDeviceObject);
|
|
if (!m_NextDeviceObject)
|
|
{
|
|
//
|
|
// failed to attach to device stack
|
|
//
|
|
IoDeleteDevice(m_FunctionalDeviceObject);
|
|
m_FunctionalDeviceObject = 0;
|
|
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
|
|
//
|
|
// initialize hardware object
|
|
//
|
|
Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to initialize hardware object %x\n", Status);
|
|
|
|
//
|
|
// failed to initialize hardware object, detach from device stack
|
|
//
|
|
IoDetachDevice(m_NextDeviceObject);
|
|
|
|
//
|
|
// now delete the device
|
|
//
|
|
IoDeleteDevice(m_FunctionalDeviceObject);
|
|
|
|
//
|
|
// nullify pointers :)
|
|
//
|
|
m_FunctionalDeviceObject = 0;
|
|
m_NextDeviceObject = 0;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//
|
|
// set device flags
|
|
//
|
|
m_FunctionalDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
|
|
|
|
|
//
|
|
// get device extension
|
|
//
|
|
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_FunctionalDeviceObject->DeviceExtension;
|
|
PC_ASSERT(DeviceExtension);
|
|
|
|
//
|
|
// initialize device extension
|
|
//
|
|
DeviceExtension->IsFDO = TRUE;
|
|
DeviceExtension->IsHub = FALSE;
|
|
DeviceExtension->Dispatcher = PDISPATCHIRP(this);
|
|
|
|
//
|
|
// device is initialized
|
|
//
|
|
m_FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
//
|
|
// is there a root controller
|
|
//
|
|
if (m_RootController)
|
|
{
|
|
//
|
|
// add reference
|
|
//
|
|
m_RootController->AddRef();
|
|
|
|
//
|
|
// register with controller
|
|
//
|
|
m_RootController->RegisterHCD(this);
|
|
}
|
|
|
|
|
|
//
|
|
// done
|
|
//
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
NTSTATUS
|
|
CHCDController::HandleDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
|
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
|
|
PUSB_HCD_DRIVERKEY_NAME DriverKey;
|
|
ULONG ResultLength;
|
|
|
|
//
|
|
// get current stack location
|
|
//
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// get device extension
|
|
//
|
|
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// sanity check
|
|
//
|
|
PC_ASSERT(DeviceExtension->IsFDO);
|
|
|
|
DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n",
|
|
IoStack->Parameters.DeviceIoControl.IoControlCode,
|
|
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
|
|
|
//
|
|
// perform ioctl for FDO
|
|
//
|
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME)
|
|
{
|
|
//
|
|
// check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
|
|
//
|
|
if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
|
|
{
|
|
//
|
|
// get device property size
|
|
//
|
|
Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, 0, NULL, &ResultLength);
|
|
|
|
//
|
|
// get input buffer
|
|
//
|
|
DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
//
|
|
// check result
|
|
//
|
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
//
|
|
// does the caller provide enough buffer space
|
|
//
|
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= ResultLength)
|
|
{
|
|
//
|
|
// it does
|
|
//
|
|
Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// informal debug print
|
|
//
|
|
DPRINT1("Result %S\n", DriverKey->DriverKeyName);
|
|
}
|
|
}
|
|
|
|
//
|
|
// store result
|
|
//
|
|
DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
|
|
Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// buffer is certainly too small
|
|
//
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
|
|
}
|
|
}
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_ROOT_HUB_NAME)
|
|
{
|
|
//
|
|
// check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
|
|
//
|
|
if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
|
|
{
|
|
//
|
|
// sanity check
|
|
//
|
|
PC_ASSERT(m_HubController);
|
|
|
|
//
|
|
// get input buffer
|
|
//
|
|
DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
//
|
|
// get symbolic link
|
|
//
|
|
Status = m_HubController->GetHubControllerSymbolicLink(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// null terminate it
|
|
//
|
|
PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG) - sizeof(WCHAR) >= ResultLength);
|
|
|
|
DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] = L'\0';
|
|
DPRINT1("Result %S\n", DriverKey->DriverKeyName);
|
|
}
|
|
|
|
//
|
|
// store result
|
|
//
|
|
DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
|
|
Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// buffer is certainly too small
|
|
//
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
|
|
}
|
|
}
|
|
|
|
//
|
|
// complete the request
|
|
//
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
//
|
|
// done
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
CHCDController::HandlePnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
|
PCM_RESOURCE_LIST RawResourceList;
|
|
PCM_RESOURCE_LIST TranslatedResourceList;
|
|
PDEVICE_RELATIONS DeviceRelations;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// get device extension
|
|
//
|
|
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// sanity check
|
|
//
|
|
PC_ASSERT(DeviceExtension->IsFDO);
|
|
|
|
//
|
|
// get current stack location
|
|
//
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
switch(IoStack->MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE:
|
|
{
|
|
DPRINT1("CHCDController::HandlePnp IRP_MN_START FDO\n");
|
|
|
|
//
|
|
// first start lower device object
|
|
//
|
|
Status = SyncForwardIrp(m_NextDeviceObject, Irp);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// operation succeeded, lets start the device
|
|
//
|
|
RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
|
|
TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
|
|
|
|
if (m_Hardware)
|
|
{
|
|
//
|
|
// start the hardware
|
|
//
|
|
Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
|
|
}
|
|
|
|
//
|
|
// enable symbolic link
|
|
//
|
|
Status = SetSymbolicLink(TRUE);
|
|
}
|
|
|
|
DPRINT1("CHCDController::HandlePnp IRP_MN_START FDO: Status %x\n", Status);
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
{
|
|
DPRINT1("CHCDController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", IoStack->Parameters.QueryDeviceRelations.Type);
|
|
|
|
if (m_HubController == NULL)
|
|
{
|
|
//
|
|
// create hub controller
|
|
//
|
|
Status = CreateHubController(&m_HubController);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// failed to create hub controller
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// initialize hub controller
|
|
//
|
|
Status = m_HubController->Initialize(m_DriverObject, PHCDCONTROLLER(this), m_Hardware, TRUE, 0 /* FIXME*/);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// failed to initialize hub controller
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// add reference to prevent it from getting deleting while hub driver adds / removes references
|
|
//
|
|
m_HubController->AddRef();
|
|
}
|
|
|
|
if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
|
|
{
|
|
//
|
|
// allocate device relations
|
|
//
|
|
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
|
|
|
|
if (!DeviceRelations)
|
|
{
|
|
//
|
|
// no memory
|
|
//
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// init device relations
|
|
//
|
|
DeviceRelations->Count = 1;
|
|
Status = m_HubController->GetHubControllerDeviceObject(&DeviceRelations->Objects [0]);
|
|
|
|
//
|
|
// sanity check
|
|
//
|
|
PC_ASSERT(Status == STATUS_SUCCESS);
|
|
|
|
ObReferenceObject(DeviceRelations->Objects [0]);
|
|
|
|
//
|
|
// store result
|
|
//
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// not supported
|
|
//
|
|
PC_ASSERT(0);
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
}
|
|
break;
|
|
}
|
|
case IRP_MN_STOP_DEVICE:
|
|
{
|
|
DPRINT1("CHCDController::HandlePnp IRP_MN_STOP_DEVICE\n");
|
|
|
|
if (m_Hardware)
|
|
{
|
|
//
|
|
// stop the hardware
|
|
//
|
|
Status = m_Hardware->PnpStop();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// fake success
|
|
//
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// stop lower device
|
|
//
|
|
Status = SyncForwardIrp(m_NextDeviceObject, Irp);
|
|
}
|
|
break;
|
|
}
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
{
|
|
DPRINT1("CHCDController::HandlePnp IRP_MN_REMOVE_DEVICE FDO\n");
|
|
|
|
//
|
|
// detach device from device stack
|
|
//
|
|
IoDetachDevice(m_NextDeviceObject);
|
|
|
|
//
|
|
// delete device
|
|
//
|
|
IoDeleteDevice(m_FunctionalDeviceObject);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
//
|
|
// forward irp to next device object
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return IoCallDriver(m_NextDeviceObject, Irp);
|
|
}
|
|
}
|
|
|
|
//
|
|
// store result and complete request
|
|
//
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
CHCDController::HandlePower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
UNIMPLEMENTED
|
|
|
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
CHCDController::CreateFDO(
|
|
PDRIVER_OBJECT DriverObject,
|
|
PDEVICE_OBJECT * OutDeviceObject)
|
|
{
|
|
WCHAR CharDeviceName[64];
|
|
NTSTATUS Status;
|
|
ULONG UsbDeviceNumber = 0;
|
|
UNICODE_STRING DeviceName;
|
|
|
|
while (TRUE)
|
|
{
|
|
//
|
|
// construct device name
|
|
//
|
|
swprintf(CharDeviceName, L"\\Device\\USBFDO-%d", UsbDeviceNumber);
|
|
|
|
//
|
|
// initialize device name
|
|
//
|
|
RtlInitUnicodeString(&DeviceName, CharDeviceName);
|
|
|
|
//
|
|
// create device
|
|
//
|
|
Status = IoCreateDevice(DriverObject,
|
|
sizeof(COMMON_DEVICE_EXTENSION),
|
|
&DeviceName,
|
|
FILE_DEVICE_CONTROLLER,
|
|
0,
|
|
FALSE,
|
|
OutDeviceObject);
|
|
|
|
//
|
|
// check for success
|
|
//
|
|
if (NT_SUCCESS(Status))
|
|
break;
|
|
|
|
//
|
|
// is there a device object with that same name
|
|
//
|
|
if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
|
|
{
|
|
//
|
|
// Try the next name
|
|
//
|
|
UsbDeviceNumber++;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// bail out on other errors
|
|
//
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("CreateFDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// store FDO number
|
|
//
|
|
m_FDODeviceNumber = UsbDeviceNumber;
|
|
|
|
DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
|
|
|
|
/* done */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
CHCDController::SetSymbolicLink(
|
|
BOOLEAN Enable)
|
|
{
|
|
NTSTATUS Status;
|
|
WCHAR LinkName[32];
|
|
WCHAR FDOName[32];
|
|
UNICODE_STRING Link, FDO;
|
|
|
|
if (Enable)
|
|
{
|
|
//
|
|
// create legacy link
|
|
//
|
|
swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
|
|
swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber);
|
|
RtlInitUnicodeString(&Link, LinkName);
|
|
RtlInitUnicodeString(&FDO, FDOName);
|
|
|
|
//
|
|
// create symbolic link
|
|
//
|
|
Status = IoCreateSymbolicLink(&Link, &FDO);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// FIXME: handle me
|
|
//
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// create legacy link
|
|
//
|
|
swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
|
|
RtlInitUnicodeString(&Link, LinkName);
|
|
|
|
//
|
|
// now delete the symbolic link
|
|
//
|
|
Status = IoDeleteSymbolicLink(&Link);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// FIXME: handle me
|
|
//
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// done
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
CreateHCDController(
|
|
PHCDCONTROLLER *OutHcdController)
|
|
{
|
|
PHCDCONTROLLER This;
|
|
|
|
//
|
|
// allocate controller
|
|
//
|
|
This = new(NonPagedPool, TAG_USBEHCI) CHCDController(0);
|
|
if (!This)
|
|
{
|
|
//
|
|
// failed to allocate
|
|
//
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// add reference count
|
|
//
|
|
This->AddRef();
|
|
|
|
//
|
|
// return result
|
|
//
|
|
*OutHcdController = (PHCDCONTROLLER)This;
|
|
|
|
//
|
|
// done
|
|
//
|
|
return STATUS_SUCCESS;
|
|
}
|