return STATUS_SUCCESS;
}
+NTSTATUS
+USBCCGP_PdoAppendInterfaceNumber(
+ IN LPWSTR DeviceId,
+ IN ULONG InterfaceNumber,
+ OUT LPWSTR *OutString)
+{
+ ULONG Length = 0, StringLength;
+ LPWSTR String;
+
+ //
+ // count length of string
+ //
+ String = DeviceId;
+ while(*String)
+ {
+ StringLength = wcslen(String) + 1;
+ Length += StringLength;
+ Length += 6; //&MI_XX
+ String += StringLength;
+ }
+
+ //
+ // now allocate the buffer
+ //
+ String = AllocateItem(NonPagedPool, (Length + 2) * sizeof(WCHAR));
+ if (!String)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // store result
+ //
+ *OutString = String;
+
+ while(*DeviceId)
+ {
+ StringLength = swprintf(String, L"%s&MI_%02x", DeviceId) + 1;
+ Length = wcslen(DeviceId) + 1;
+ DPRINT1("String %p\n", String);
+
+ //
+ // next string
+ //
+ String += StringLength;
+ DeviceId += Length;
+ }
+
+ //
+ // success
+ //
+ return STATUS_SUCCESS;
+}
+
+
NTSTATUS
USBCCGP_PdoHandleQueryId(
PDEVICE_OBJECT DeviceObject,
{
PIO_STACK_LOCATION IoStack;
PUNICODE_STRING DeviceString = NULL;
- UNICODE_STRING TempString;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
NTSTATUS Status;
LPWSTR Buffer;
// handle query device id
//
Status = USBCCGP_SyncForwardIrp(PDODeviceExtension->NextDeviceObject, Irp);
-
- //
- // FIXME append interface id
- //
- UNIMPLEMENTED
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // allocate buffer
+ //
+ Buffer = AllocateItem(NonPagedPool, (wcslen((LPWSTR)Irp->IoStatus.Information) + 7) * sizeof(WCHAR));
+ if (Buffer)
+ {
+ //
+ // append interface number
+ //
+ ASSERT(Irp->IoStatus.Information);
+ swprintf(Buffer, L"%s&MI_%02x", (LPWSTR)Irp->IoStatus.Information, PDODeviceExtension->FunctionDescriptor->FunctionNumber);
+ DPRINT1("BusQueryDeviceID %S\n", Buffer);
+
+ ExFreePool((PVOID)Irp->IoStatus.Information);
+ Irp->IoStatus .Information = (ULONG_PTR)Buffer;
+ }
+ else
+ {
+ //
+ // no memory
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
return Status;
}
else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
//
// handle instance id
//
- RtlInitUnicodeString(&TempString, L"0000");
- DeviceString = &TempString;
+ Buffer = AllocateItem(NonPagedPool, 5 * sizeof(WCHAR));
+ if (!Buffer)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // use function number
+ //
+ swprintf(Buffer, L"%04x", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+ return STATUS_SUCCESS;
}
else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
{
//
// copy buffer
//
- Irp->IoStatus.Information = (ULONG_PTR)Buffer;
RtlCopyMemory(Buffer, DeviceString->Buffer, DeviceString->Length);
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+
return STATUS_SUCCESS;
}
PIO_STACK_LOCATION IoStack;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
NTSTATUS Status;
+ ULONG Index;
//
// get current stack location
}
case IRP_MN_REMOVE_DEVICE:
{
- DPRINT1("IRP_MN_REMOVE_DEVICE\n");
+ //
+ // remove us from the fdo's pdo list
+ //
+ for(Index = 0; Index < PDODeviceExtension->FDODeviceExtension->FunctionDescriptorCount; Index++)
+ {
+ if (PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] == DeviceObject)
+ {
+ //
+ // remove us
+ //
+ PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] = NULL;
+ break;
+ }
+ }
- /* Complete the IRP */
+ //
+ // Complete the IRP
+ //
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- /* Delete the device object */
+ //
+ // Delete the device object
+ //
IoDeleteDevice(DeviceObject);
-
return STATUS_SUCCESS;
}
case IRP_MN_QUERY_CAPABILITIES:
}
+NTSTATUS
+USBCCGP_BuildConfigurationDescriptor(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ ULONG TotalSize, Index;
+ PURB Urb;
+ PVOID Buffer;
+ PUCHAR BufferPtr;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT1("USBCCGP_BuildConfigurationDescriptor\n");
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get configuration descriptor
+ //
+ ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor;
+
+ //
+ // calculate size of configuration descriptor
+ //
+ TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
+
+ for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
+ {
+ //
+ // get current interface descriptor
+ //
+ InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
+
+ //
+ // add to size and move to next descriptor
+ //
+ TotalSize += InterfaceDescriptor->bLength;
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
+
+ do
+ {
+ if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
+ {
+ //
+ // reached end of configuration descriptor
+ //
+ break;
+ }
+
+ //
+ // association descriptors are removed
+ //
+ if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
+ {
+ if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
+ {
+ //
+ // reached next descriptor
+ //
+ break;
+ }
+
+ //
+ // append size
+ //
+ TotalSize += InterfaceDescriptor->bLength;
+ }
+
+ //
+ // move to next descriptor
+ //
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
+ }while(TRUE);
+ }
+
+ //
+ // now allocate temporary buffer for the configuration descriptor
+ //
+ Buffer = AllocateItem(NonPagedPool, TotalSize);
+ if (!Buffer)
+ {
+ //
+ // failed to allocate buffer
+ //
+ DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // first copy the configuration descriptor
+ //
+ RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
+ BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
+
+ for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
+ {
+ //
+ // get current interface descriptor
+ //
+ InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
+
+ //
+ // copy descriptor and move to next descriptor
+ //
+ RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
+ BufferPtr += InterfaceDescriptor->bLength;
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
+
+ do
+ {
+ if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
+ {
+ //
+ // reached end of configuration descriptor
+ //
+ break;
+ }
+
+ //
+ // association descriptors are removed
+ //
+ if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
+ {
+ if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
+ {
+ //
+ // reached next descriptor
+ //
+ break;
+ }
+
+ //
+ // copy descriptor
+ //
+ RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
+ BufferPtr += InterfaceDescriptor->bLength;
+ }
+
+ //
+ // move to next descriptor
+ //
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
+ }while(TRUE);
+ }
+
+ //
+ // modify configuration descriptor
+ //
+ ConfigurationDescriptor = Buffer;
+ ConfigurationDescriptor->wTotalLength = TotalSize;
+ ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+ ASSERT(Urb);
+
+ //
+ // copy descriptor
+ //
+ RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
+
+ //
+ // store final size
+ //
+ Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
+
+ //
+ // free buffer
+ //
+ FreeItem(Buffer);
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBCCGP_PDOSelectConfiguration(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PURB Urb, NewUrb;
+ PUSBD_INTERFACE_INFORMATION InterfaceInformation;
+ ULONG InterfaceInformationCount, Index, InterfaceIndex;
+ PUSBD_INTERFACE_LIST_ENTRY Entry;
+ ULONG NeedSelect, FoundInterface;
+ NTSTATUS Status;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+ ASSERT(Urb);
+
+ //
+ // is there already an configuration handle
+ //
+ if (Urb->UrbSelectConfiguration.ConfigurationHandle)
+ {
+ //
+ // nothing to do
+ //
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // count interface information
+ //
+ InterfaceInformationCount = 0;
+ InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
+ do
+ {
+ InterfaceInformationCount++;
+ InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
+ }while((ULONG_PTR)InterfaceInformation < (ULONG_PTR)Urb + Urb->UrbSelectConfiguration.Hdr.Length);
+
+ //
+ // check all interfaces
+ //
+ InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
+ Index = 0;
+ Entry = NULL;
+ DPRINT1("Count %x\n", InterfaceInformationCount);
+ do
+ {
+ DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
+
+ //
+ // search for the interface in the local interface list
+ //
+ FoundInterface = FALSE;
+ for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++)
+ {
+ if (PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[InterfaceIndex]->bInterfaceNumber == InterfaceInformation->InterfaceNumber)
+ {
+ // found interface entry
+ FoundInterface = TRUE;
+ break;
+ }
+ }
+
+ if (!FoundInterface)
+ {
+ //
+ // invalid parameter
+ //
+ DPRINT1("InterfaceInformation InterfaceNumber %x Alternative %x NumberOfPipes %x not found\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
+ ASSERT(FALSE);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // now query the total interface list
+ //
+ Entry = NULL;
+ for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
+ {
+ if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber)
+ {
+ //
+ // found entry
+ //
+ Entry = &PDODeviceExtension->InterfaceList[InterfaceIndex];
+ }
+ }
+
+ //
+ // sanity check
+ //
+ ASSERT(Entry);
+ if (!Entry)
+ {
+ //
+ // corruption detected
+ //
+ KeBugCheck(0);
+ }
+
+ NeedSelect = FALSE;
+ if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting)
+ {
+
+ for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++)
+ {
+ if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize)
+ {
+ //
+ // changed interface
+ //
+ NeedSelect = TRUE;
+ }
+ }
+ }
+ else
+ {
+ //
+ // need select as the interface number differ
+ //
+ NeedSelect = TRUE;
+ }
+
+ if (!NeedSelect)
+ {
+ //
+ // interface is already selected
+ //
+ RtlCopyMemory(InterfaceInformation, Entry->Interface, min(InterfaceInformation->Length, Entry->Interface->Length));
+ }
+ else
+ {
+ //
+ // select interface
+ //
+ DPRINT1("Selecting InterfaceIndex %lu AlternateSetting %lu NumberOfPipes %lu\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
+ ASSERT(InterfaceInformation->Length == Entry->Interface->Length);
+
+ //
+ // build urb
+ //
+ NewUrb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes));
+ if (!NewUrb)
+ {
+ //
+ // no memory
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // now prepare interface urb
+ //
+ UsbBuildSelectInterfaceRequest(NewUrb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
+
+ //
+ // now select the interface
+ //
+ Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb);
+ DPRINT1("SelectInterface Status %x\n", Status);
+
+ //
+ // did it succeeed
+ //
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // update configuration info
+ //
+ ASSERT(Entry->Interface->Length == NewUrb->UrbSelectInterface.Interface.Length);
+ ASSERT(InterfaceInformation->Length == NewUrb->UrbSelectInterface.Interface.Length);
+ RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
+
+ //
+ // update provided interface information
+ //
+ RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
+ }
+
+ //
+ // free urb
+ //
+ FreeItem(NewUrb);
+ }
+
+ //
+ // move to next information
+ //
+ InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
+ Index++;
+ }while(Index < InterfaceInformationCount);
+
+ //
+ // store configuration handle
+ //
+ Urb->UrbSelectConfiguration.ConfigurationHandle = PDODeviceExtension->ConfigurationHandle;
+
+ DPRINT1("[USBCCGP] SelectConfiguration Function %x Completed\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PDO_HandleInternalDeviceControl(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ NTSTATUS Status;
+ PURB Urb;
+
+ //
+ // get current stack location
+ //
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // get device extension
+ //
+ PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
+ {
+ //
+ // get urb
+ //
+ Urb = (PURB)IoStack->Parameters.Others.Argument1;
+ ASSERT(Urb);
+ DPRINT("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
+
+ if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION)
+ {
+ //
+ // select configuration
+ //
+ Status = USBCCGP_PDOSelectConfiguration(DeviceObject, Irp);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
+ {
+ if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
+ {
+ //
+ // is the buffer big enough
+ //
+ if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
+ {
+ //
+ // invalid buffer size
+ //
+ DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
+ Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
+ Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_BUFFER_SIZE;
+ }
+
+ //
+ // copy device descriptor
+ //
+ ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+ RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
+ else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
+ {
+ //
+ // build configuration descriptor
+ //
+ Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ }
+ else
+ {
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
+ return Status;
+ }
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_GET_PORT_STATUS)
+ {
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
+ return Status;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
+ {
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
+ return Status;
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
+ {
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
+ return Status;
+ }
+
+
+
+ DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+ DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
+ DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+ DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
+
+ ASSERT(FALSE);
+
+ Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS
PDO_Dispatch(
{
case IRP_MJ_PNP:
return PDO_HandlePnp(DeviceObject, Irp);
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+ return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
default:
DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
ASSERT(FALSE);