www.pudn.com > data-isotransfer.rar > TestPnp.c


#include "usbdriver.h" 
 
NTSTATUS PnpHandleStartDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp); 
NTSTATUS ForwardAndWait(IN PDEVICE_OBJECT fdo,IN PIRP Irp); 
NTSTATUS ForwardIrpComplete(IN PDEVICE_OBJECT fdo, 
						    IN PIRP Irp, 
                            IN PKEVENT pev); 
NTSTATUS UsbStartDevice(IN PDEVICE_OBJECT fdo); 
NTSTATUS UsbConfigureDevice(IN  PDEVICE_OBJECT fdo); 
NTSTATUS UsbSelectInterfaces(IN PDEVICE_OBJECT fdo, 
            IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, 
            IN PUSBD_INTERFACE_INFORMATION Interface); 
NTSTATUS PnpHandleDefault(IN PDEVICE_OBJECT fdo,IN PIRP Irp); 
NTSTATUS PnpHandleStopDevice(IN  PDEVICE_OBJECT fdo); 
NTSTATUS PnpHandleRemoveDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp); 
NTSTATUS UsbRemoveDevice(IN PDEVICE_OBJECT fdo); 
// 
NTSTATUS TestAddDevice(IN PDRIVER_OBJECT DriverObject, 
                       IN PDEVICE_OBJECT PhysicalDeviceObject) 
{ 
	NTSTATUS ntStatus = STATUS_SUCCESS; 
    WCHAR KernelDeviceNameBuffer[] = L"\\Device\\Ezusb-0";   
    UNICODE_STRING KernelDeviceNameUnicode;					 
    WCHAR UserDeviceLinkBuffer[] = L"\\DosDevices\\Ezusb-0"; 
    UNICODE_STRING UserDeviceLinkUnicode; 
    PDEVICE_OBJECT fdo = NULL;  
    PDEVICE_EXTENSION pdx;   
	 
    RtlInitUnicodeString (&KernelDeviceNameUnicode, 
                          KernelDeviceNameBuffer); 
  
    ntStatus = IoCreateDevice (DriverObject, 
                               sizeof (DEVICE_EXTENSION), 
                               &KernelDeviceNameUnicode, 
                               FILE_DEVICE_UNKNOWN, 
                               0, 
                               FALSE, 
                               &fdo); 
   
    if( !NT_SUCCESS(ntStatus)) 
		return ntStatus; 
 
	RtlInitUnicodeString (&UserDeviceLinkUnicode, 
                          UserDeviceLinkBuffer); 
 
    ntStatus = IoCreateSymbolicLink (&UserDeviceLinkUnicode, 
                                     &KernelDeviceNameUnicode);  
 
    pdx = (PDEVICE_EXTENSION) (fdo->DeviceExtension); 
 
    RtlCopyMemory(pdx->DeviceLinkName, 
                  UserDeviceLinkBuffer, 
                  sizeof(UserDeviceLinkBuffer)); 
 
    pdx->OpenHandles = 0;	   
    pdx->ConfigurationHandle = NULL; 
    pdx->DeviceDescriptor = NULL; 
    pdx->Interface = NULL; 
        
    fdo->Flags &= ~DO_DEVICE_INITIALIZING; 
 
    fdo->Flags |= DO_DIRECT_IO; 
 
    pdx->PhysicalDeviceObject=PhysicalDeviceObject; 
	   
    pdx->LowerDeviceObject = 
         IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject); 
 
    pdx->Usages = 1;   
    KeInitializeEvent(&pdx->evRemove, 
                      NotificationEvent, 
                      FALSE);   
    return ntStatus; 
} 
// 
NTSTATUS TestPnpIrp(IN PDEVICE_OBJECT fdo, IN PIRP Irp) 
{ 
	NTSTATUS ntStatus=STATUS_SUCCESS; 
	PIO_STACK_LOCATION IrpStack; 
    PDEVICE_EXTENSION pdx = fdo->DeviceExtension; 
    ULONG MinorFunction; 
 
    if (!LockDevice(fdo)) 
		return CompleteRequest(Irp, STATUS_DELETE_PENDING, 0); 
 
    IrpStack = IoGetCurrentIrpStackLocation (Irp); 
    MinorFunction = IrpStack->MinorFunction; 
 
    switch (MinorFunction) 
		{ 
		case IRP_MN_START_DEVICE: 
			ntStatus = PnpHandleStartDevice(fdo,Irp); 
			break;  
 
        case IRP_MN_STOP_DEVICE: 
         PnpHandleDefault(fdo,Irp); 
         ntStatus = PnpHandleStopDevice(fdo); 
         break;  
 
         case IRP_MN_REMOVE_DEVICE: 
		  ntStatus = PnpHandleRemoveDevice(fdo,Irp); 
          break; 
 
        case IRP_MN_QUERY_CAPABILITIES: 
		  { 
			  PDEVICE_CAPABILITIES pdc = IrpStack->Parameters.DeviceCapabilities.Capabilities; 
		      if (pdc->Version < 1) { 
				  ntStatus = PnpHandleDefault(fdo, Irp); 
                  break; 
			  } 
              ntStatus = ForwardAndWait(fdo, Irp); 
			  if (NT_SUCCESS(ntStatus)) {   
				  pdc = IrpStack->Parameters.DeviceCapabilities.Capabilities; 
           	      pdc->SurpriseRemovalOK = TRUE; 
			  } 
   		      ntStatus = CompleteRequest(Irp, ntStatus, Irp->IoStatus.Information); 
		  } 
          break;  
       default: 
		 ntStatus = PnpHandleDefault(fdo, Irp); 
   }  
   if (MinorFunction != IRP_MN_REMOVE_DEVICE) 
	   UnlockDevice(fdo); 
 
   return ntStatus; 
} 
// 
BOOLEAN LockDevice(IN PDEVICE_OBJECT fdo) 
{ 
   PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
 
   LONG usage = InterlockedIncrement(&pdx->Usages); 
 
   if (pdx->Removing) { 
	   if (InterlockedDecrement(&pdx->Usages) == 0) 
		   KeSetEvent(&pdx->evRemove, 0, FALSE); 
	   return FALSE; 
   } 
   return TRUE; 
} 
// 
void UnlockDevice(PDEVICE_OBJECT fdo) 
{ 
	PDEVICE_EXTENSION pdx; 
	LONG usage; 
 
	pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
    usage = InterlockedDecrement(&pdx->Usages); 
 
    if (usage == 0) {	 
		KeSetEvent(&pdx->evRemove, 0, FALSE); 
   }					 
} 
// 
NTSTATUS CompleteRequest(IN PIRP Irp, 
						 IN NTSTATUS status, 
						 IN ULONG info) 
{ 
	Irp->IoStatus.Status = status; 
	Irp->IoStatus.Information = info; 
	IoCompleteRequest(Irp, IO_NO_INCREMENT); 
	 
	return status; 
} 
// 
NTSTATUS PnpHandleStartDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{ 
	NTSTATUS ntStatus; 
	 
    ntStatus = ForwardAndWait(fdo, Irp); 
	if (!NT_SUCCESS(ntStatus)) 
		return CompleteRequest(Irp, ntStatus, Irp->IoStatus.Information); 
    ntStatus = UsbStartDevice(fdo); 
     
	return CompleteRequest(Irp, ntStatus, 0); 
} 
// 
NTSTATUS ForwardAndWait(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{ 
	NTSTATUS ntStatus; 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	KEVENT event; 
 
	KeInitializeEvent(&event, NotificationEvent, FALSE); 
 
	IoCopyCurrentIrpStackLocationToNext(Irp); 
	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)ForwardIrpComplete, 
		                  (PVOID) &event, TRUE, TRUE, TRUE); 
 
	ntStatus = IoCallDriver(pdx->LowerDeviceObject, Irp); 
 
	if (ntStatus == STATUS_PENDING)	{ 
		KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); 
        ntStatus = Irp->IoStatus.Status; 
    } 
	return ntStatus; 
} 
// 
NTSTATUS ForwardIrpComplete(IN PDEVICE_OBJECT fdo, 
						    IN PIRP Irp, 
                            IN PKEVENT pev) 
{ 
   KeSetEvent(pev, 0, FALSE); 
   return STATUS_MORE_PROCESSING_REQUIRED; 
} 
// 
NTSTATUS UsbStartDevice(IN PDEVICE_OBJECT fdo) 
{ 
	NTSTATUS ntStatus; 
    PDEVICE_EXTENSION pdx; 
    PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL; 
    PURB urb; 
    USHORT SizeUrb; 
	ULONG SizeDescriptor; 
 
	pdx = fdo->DeviceExtension; 
 
    SizeUrb=sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); 
	urb = ExAllocatePool( NonPagedPool,SizeUrb); 
    if (urb==NULL) 	return STATUS_NO_MEMORY; 
	 
	SizeDescriptor = sizeof(USB_DEVICE_DESCRIPTOR); 
    deviceDescriptor = ExAllocatePool(NonPagedPool,SizeDescriptor); 
    if (deviceDescriptor==NULL) { 
		ExFreePool(urb); 
        return STATUS_NO_MEMORY; 
	} 
 
	UsbBuildGetDescriptorRequest(urb, 
                                SizeUrb, 
                                USB_DEVICE_DESCRIPTOR_TYPE, 
                                0, 
                                0, 
                                deviceDescriptor, 
                                NULL, 
                                SizeDescriptor, 
                                NULL); 
 
   ntStatus = UsbCallUSBDI(fdo, urb); 
   if (NT_SUCCESS(ntStatus)) { 
       pdx->DeviceDescriptor = deviceDescriptor; 
       pdx->Stop = FALSE; 
   } 
   else  { 
   	ExFreePool(deviceDescriptor); 
	pdx->DeviceDescriptor = NULL; 
	} 
   
   ExFreePool(urb); 
 
   if (NT_SUCCESS(ntStatus)) { 
        ntStatus = UsbConfigureDevice(fdo); 
    } 
     
    return ntStatus; 
} 
// 
NTSTATUS UsbCallUSBDI(IN PDEVICE_OBJECT fdo,IN PURB Urb) 
{ 
     
    NTSTATUS ntStatus, status = STATUS_SUCCESS; 
    PDEVICE_EXTENSION pdx; 
    PIRP irp; 
    KEVENT event; 
    IO_STATUS_BLOCK ioStatus; 
    PIO_STACK_LOCATION nextStack; 
 
    pdx = fdo->DeviceExtension; 
 
    KeInitializeEvent(&event, NotificationEvent, FALSE); 
    irp = IoBuildDeviceIoControlRequest( 
                                        IOCTL_INTERNAL_USB_SUBMIT_URB, 
                                        pdx->LowerDeviceObject, 
                                        NULL, 
                                        0, 
                                        NULL, 
                                        0, 
                                        TRUE,  
                                        &event, 
                                        &ioStatus); 
    nextStack = IoGetNextIrpStackLocation(irp); 
 
    nextStack->Parameters.Others.Argument1 = Urb; 
 
 
    ntStatus = IoCallDriver(pdx->LowerDeviceObject,irp); 
    if (ntStatus == STATUS_PENDING) { 
		KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL); 
	    ntStatus=ioStatus.Status; 
    } 
 
    if (NT_SUCCESS(ntStatus)) { 
	    if (!(USBD_SUCCESS(Urb->UrbHeader.Status))) 
	    	   ntStatus = STATUS_UNSUCCESSFUL; 
    } 
 
    return ntStatus; 
} 
// 
NTSTATUS UsbConfigureDevice(IN  PDEVICE_OBJECT fdo) 
{ 
	NTSTATUS ntStatus; 
	PDEVICE_EXTENSION pdx; 
    PURB urb = NULL; 
    USHORT SizeUrb; 
	ULONG  SizeDescriptor; 
    PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL; 
     
    pdx = fdo->DeviceExtension; 
 
    SizeUrb = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); 
	urb = ExAllocatePool(NonPagedPool,SizeUrb); 
    if (urb == NULL)  return STATUS_NO_MEMORY; 
 
    SizeDescriptor=sizeof(USB_CONFIGURATION_DESCRIPTOR) + 16; 
 
    configurationDescriptor = ExAllocatePool(NonPagedPool, SizeDescriptor); 
 
	if (configurationDescriptor == NULL) { 
		ExFreePool(urb);        
		return STATUS_NO_MEMORY; 
    } 
	UsbBuildGetDescriptorRequest(urb, 
                                 SizeUrb, 
                                 USB_CONFIGURATION_DESCRIPTOR_TYPE, 
                                 0, 
                                 0, 
                                 configurationDescriptor, 
                                 NULL, 
                                 SizeDescriptor, 
                                 NULL); 
 
	ntStatus = UsbCallUSBDI(fdo, urb); 
    if (!NT_SUCCESS(ntStatus)) { 
		ExFreePool(urb);                     
        ExFreePool(configurationDescriptor); 
        return ntStatus;	    
	} 
    SizeDescriptor = configurationDescriptor->wTotalLength + 16; 
 
    ExFreePool(configurationDescriptor); 
    configurationDescriptor = NULL; 
 
    configurationDescriptor = ExAllocatePool(NonPagedPool, SizeDescriptor); 
 
    if (configurationDescriptor == NULL) { 
        ExFreePool(urb);        
		return STATUS_NO_MEMORY; 
	} 
    UsbBuildGetDescriptorRequest(urb, 
                                 SizeUrb, 
                                 USB_CONFIGURATION_DESCRIPTOR_TYPE, 
                                 0, 
                                 0, 
                                 configurationDescriptor, 
                                 NULL, 
                                 SizeDescriptor,  
                                 NULL); 
    ntStatus = UsbCallUSBDI(fdo, urb); 
    if (!NT_SUCCESS(ntStatus)) { 
    	ExFreePool(urb);                     
        ExFreePool(configurationDescriptor); 
        return ntStatus;	    
	} 
    if (configurationDescriptor) { 
        ntStatus = UsbSelectInterfaces(fdo, 
                                       configurationDescriptor, 
                                       NULL 
                                       ); 
    }  
    ExFreePool(urb);  
    ExFreePool(configurationDescriptor); 
 
    return ntStatus;	    
} 
// 
NTSTATUS UsbSelectInterfaces(IN PDEVICE_OBJECT fdo, 
            IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, 
            IN PUSBD_INTERFACE_INFORMATION Interface) 
{ 
	NTSTATUS ntStatus; 
	PDEVICE_EXTENSION pdx; 
    PURB urb; 
    ULONG i; 
    UCHAR alternateSetting, MyInterfaceNumber; 
    PUSBD_INTERFACE_INFORMATION interfaceObject; 
    USBD_INTERFACE_LIST_ENTRY interfaceList[2]; 
 
    pdx = fdo->DeviceExtension; 
    MyInterfaceNumber = 0; 
	alternateSetting = 0; 
 
   interfaceList[0].InterfaceDescriptor = USBD_ParseConfigurationDescriptor(ConfigurationDescriptor, 
                                                                         MyInterfaceNumber,  
                                                                         alternateSetting); 
   interfaceList[1].InterfaceDescriptor = NULL; 
   interfaceList[1].Interface = NULL; 
	  
   urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,&interfaceList[0]); 
   interfaceObject = (PUSBD_INTERFACE_INFORMATION) (&(urb->UrbSelectConfiguration.Interface)); 
 
   for (i=0; ibNumEndpoints; i++) 
	   interfaceObject->Pipes[i].MaximumTransferSize = (64 * 1024) - 1; 
 
   ntStatus = UsbCallUSBDI(fdo, urb); 
 
   if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(urb->UrbHeader.Status)) { 
       pdx->ConfigurationHandle = 
               urb->UrbSelectConfiguration.ConfigurationHandle; 
 
      pdx->Interface = ExAllocatePool(NonPagedPool, 
                                      interfaceObject->Length); 
      RtlCopyMemory(pdx->Interface, interfaceObject, interfaceObject->Length); 
   } 
 
   return ntStatus; 
} 
// 
NTSTATUS PnpHandleDefault(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{ 
   PDEVICE_EXTENSION pdx; 
   pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
   IoSkipCurrentIrpStackLocation(Irp); 
   return IoCallDriver(pdx->LowerDeviceObject, Irp); 
} 
// 
NTSTATUS PnpHandleStopDevice(IN  PDEVICE_OBJECT fdo) 
{ 
	NTSTATUS ntStatus; 
	PDEVICE_EXTENSION pdx; 
    PURB urb; 
    ULONG size; 
 
    pdx = fdo->DeviceExtension; 
 
    size = sizeof(struct _URB_SELECT_CONFIGURATION); 
    urb = ExAllocatePool(NonPagedPool,size); 
 
    if (urb==NULL)  return STATUS_NO_MEMORY; 
    UsbBuildSelectConfigurationRequest(urb, 
                                       (USHORT)size, 
                                       NULL); 
    ntStatus = UsbCallUSBDI(fdo, urb); 
    ExFreePool(urb); 
    return ntStatus; 
} 
// 
NTSTATUS PnpHandleRemoveDevice(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 
{ 
	NTSTATUS ntStatus; 
    PDEVICE_EXTENSION pdx; 
	 
	pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	pdx->Removing = TRUE; 
	UnlockDevice(fdo);			 
	UnlockDevice(fdo);			 
	KeWaitForSingleObject(&pdx->evRemove, Executive, KernelMode, FALSE, NULL); 
 
	UsbRemoveDevice(fdo); 
    ntStatus = PnpHandleDefault(fdo, Irp); 
    return ntStatus; 
} 
// 
NTSTATUS UsbRemoveDevice(IN  PDEVICE_OBJECT fdo) 
{ 
	NTSTATUS ntStatus = STATUS_SUCCESS; 
	PDEVICE_EXTENSION pdx; 
    UNICODE_STRING deviceLinkUnicodeString; 
 
    pdx = fdo->DeviceExtension; 
    if (pdx->DeviceDescriptor)   
		ExFreePool(pdx->DeviceDescriptor); 
 
    if (pdx->Interface != NULL)   
	    ExFreePool(pdx->Interface); 
 
    RtlInitUnicodeString (&deviceLinkUnicodeString, 
                          pdx->DeviceLinkName); 
    IoDeleteSymbolicLink(&deviceLinkUnicodeString); 
    IoDetachDevice(pdx->LowerDeviceObject); 
    IoDeleteDevice (fdo); 
    return ntStatus; 
}