www.pudn.com > usb2303.rar > Usb2303Device.cpp, change:2004-10-29,size:27040b


// Usb2303Device.cpp 
// Implementation of Usb2303Device device class 
// 
// Generated by DriverWizard version DriverStudio 3.1.0 (Build 1722) 
// Requires Compuware's DriverWorks classes 
// 
 
#pragma warning(disable:4065) // Allow switch statement with no cases 
		   
#include <vdw.h> 
#include <kusb.h> 
#include "..\Usb2303Deviceinterface.h" 
 
#include "Usb2303.h" 
#include "Usb2303Device.h" 
#include "..\usb2303ioctl.h" 
 
#pragma hdrstop("Usb2303.pch") 
 
void Usb2303Device::GetStringDescriptors(); 
 
extern KDebugOnlyTrace t;	// Global driver trace object	 
 
GUID Usb2303Device_Guid = Usb2303Device_CLASS_GUID; 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::Usb2303Device 
// 
//	Routine Description: 
//		This is the constructor for the Functional Device Object, or FDO. 
//		It is derived from KPnpDevice, which builds in automatic 
//	    dispatching of subfunctions of IRP_MJ_POWER and IRP_MJ_PNP to 
//		virtual member functions. 
// 
//	Parameters: 
//		Pdo - Physical Device Object - this is a pointer to a system 
//			device object that represents the physical device. 
// 
//		Unit - Unit number. This is a number to append to the device's 
//			base device name to form the Logical Device Object's name 
// 
//	Return Value: 
//		None    
// 
//	Comments: 
//		The object being constructed contains a data member (m_Lower) of type 
//		KPnpLowerDevice. By initializing it, the driver binds the FDO to the 
//		PDO and creates an interface to the upper edge of the system class driver. 
// 
Usb2303Device::Usb2303Device(PDEVICE_OBJECT Pdo, ULONG Unit) : 
	KPnpDevice(Pdo, &Usb2303Device_Guid) 
{ 
	t << "Entering Usb2303Device::Usb2303Device (constructor)\n"; 
 
 
	// Check constructor status 
    if ( ! NT_SUCCESS(m_ConstructorStatus) ) 
	{ 
	    return; 
	} 
 
	// Remember our unit number 
	m_Unit = Unit; 
 
	// Initialize the lower device 
	m_Lower.Initialize(this, Pdo); 
 
	// Initialize the interface object.  The wizard generates code  
	// to support a single interface.  You may create and add additional  
	// interfaces.  By default, the wizard uses InterfaceNumber 0 (the  
	// first interface descriptor), ConfigurationValue 1 (the first 
	// configuration descriptor), and initial interface alternate 
	// setting of 0.  If your device has multiple interfaces or alternate 
	// settings for an interface, you can add additional KUsbInterface 
	// objects or adjust the parameters passed to this function. 
	m_Interface.Initialize( 
					m_Lower, //KUsbLowerDevice 
					0,		 //InterfaceNumber 
					1,		 //ConfigurationValue  
					0		 //Initial Interface Alternate Setting 
					);  
 
	// Initialize each Pipe object 
	m_Endpoint1IN.Initialize(m_Lower, 0x81, 10);  
	m_Endpoint2OUT.Initialize(m_Lower, 0x2, 64);  
	m_Endpoint3IN.Initialize(m_Lower, 0x83, 64);  
 
    // Inform the base class of the lower edge device object 
	SetLowerDevice(&m_Lower); 
 
	// Initialize the PnP Policy settings to the "standard" policy 
	SetPnpPolicy(); 
 
// TODO:	Customize the PnP Policy for this device by setting 
//			flags in m_Policies. 
 
	// Initialize the Power Policy settings to the "standard" policy 
	SetPowerPolicy(); 
 
// TODO:	Customize the Power Policy for this device by setting 
//			flags in m_PowerPolicies. 
 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::~Usb2303Device 
// 
//	Routine Description: 
//		This is the destructor for the Functional Device Object, or FDO. 
// 
//	Parameters: 
//		None 
// 
//	Return Value: 
//		None 
// 
//	Comments: 
//		None 
// 
 
Usb2303Device::~Usb2303Device() 
{ 
	t << "Entering Usb2303Device::~Usb2303Device() (destructor)\n"; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::DefaultPnp 
// 
//	Routine Description: 
//		Default handler for IRP_MJ_PNP 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result returned from lower device 
// 
//	Comments: 
//		This routine just passes the IRP through to the lower device. It is  
//		the default handler for IRP_MJ_PNP. IRPs that correspond to 
//		any virtual members of KpnpDevice that handle minor functions of 
//		IRP_MJ_PNP and that are not overridden get passed to this routine. 
// 
 
NTSTATUS Usb2303Device::DefaultPnp(KIrp I)  
{ 
	t << "Entering Usb2303Device::DefaultPnp\n" << I << EOL; 
 
	I.ForceReuseOfCurrentStackLocationInCalldown(); 
	return m_Lower.PnpCall(this, I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::DefaultPower 
// 
//	Routine Description: 
//		Default handler for IRP_MJ_POWER  
//   
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result returned from lower device 
// 
//	Comments: 
//		This routine just passes the IRP through to the lower device. It is  
//		the default handler for IRP_MJ_POWER. 
// 
 
NTSTATUS Usb2303Device::DefaultPower(KIrp I)  
{ 
	t << "Entering Usb2303Device::DefaultPower\n" << I << EOL; 
 
	I.IndicatePowerIrpProcessed(); 
	I.CopyParametersDown(); 
	return m_Lower.PnpPowerCall(this, I); 
} 
 
//////////////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::SystemControl 
// 
//	Routine Description: 
//		Default handler for IRP_MJ_SYSTEM_CONTROL 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result returned from lower device 
// 
//	Comments: 
//		This routine just passes the IRP through to the next device since this driver 
//		is not a WMI provider. 
// 
 
NTSTATUS Usb2303Device::SystemControl(KIrp I)  
{ 
	t << "Entering Usb2303Device::SystemControl\n"; 
 
	I.ForceReuseOfCurrentStackLocationInCalldown(); 
	return m_Lower.PnpCall(this, I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::OnStartDevice 
// 
//	Routine Description: 
//		Handler for IRP_MJ_PNP subfcn IRP_MN_START_DEVICE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		Typically, the driver sends a SET CONFIGURATION request for the 
//		USB device by using KUsbLowerDevice::ActivateConfiguration with 
//		the ConfigurationValue to activate.  The wizard generates code to  
//		support a single configuration.  You may create and add additional  
//		configurations.  
// 
 
NTSTATUS Usb2303Device::OnStartDevice(KIrp I) 
{ 
	t << "Entering Usb2303Device::OnStartDevice\n"; 
 
	NTSTATUS status = STATUS_UNSUCCESSFUL; 
 
	AC_STATUS acStatus = AC_SUCCESS; 
 
	I.Information() = 0; 
 
	// The default Pnp policy has already cleared the IRP with the lower device 
 
	//By default, the wizard passes a ConfigurationValue of 1 to  
	//ActivateConfiguration().  This corresponds to the first configuration  
	//that the device reports in its configuration descriptor.  If the device  
	//supports multiple configurations, pass the appropriate 
	//ConfigurationValue of the configuration to activate here. 
	acStatus = m_Lower.ActivateConfiguration( 
		1	// ConfigurationValue 1 (the first configuration) 
		); 
 
	switch (acStatus) 
	{ 
		case AC_SUCCESS: 
			t << "USB Configuration OK\n"; 
			GetStringDescriptors(); 
			status = STATUS_SUCCESS; 
			break; 
 
		case AC_COULD_NOT_LOCATE_INTERFACE: 
			t << "Could not locate interface\n"; 
			break; 
 
		case AC_COULD_NOT_PRECONFIGURE_INTERFACE: 
			t << "Could not get configuration descriptor\n"; 
			break; 
 
		case AC_CONFIGURATION_REQUEST_FAILED: 
			t << "Board did not accept configuration URB\n"; 
			break; 
 
		case AC_FAILED_TO_INITIALIZE_INTERFACE_OBJECT: 
			t << "Failed to initialize interface object\n"; 
			break; 
 
		case AC_FAILED_TO_GET_DESCRIPTOR: 
			t << "Failed to get device descriptor\n"; 
			break; 
 
		case AC_FAILED_TO_OPEN_PIPE_OBJECT: 
			//NOTE: this may not be an error.  It could mean that 
			//the device has an endpoint for which a KUsbPipe object has 
			//not been instanced.  If the intention is to not use this endpoint, 
			//then it's likely not a problem.   
			status = STATUS_SUCCESS; 
			t << "Failed to open pipe object\n"; 
			break; 
 
		default: 
			t << "Unexpected error activating USB configuration\n"; 
			break; 
	} 
 
   return status;  // base class completes the IRP 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::OnStopDevice 
// 
//	Routine Description: 
//		Handler for IRP_MJ_PNP subfcn IRP_MN_STOP_DEVICE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		The system calls this when the device is stopped. 
//		The driver should release any hardware resources 
//		in this routine. 
// 
//		The base class passes the irp to the lower device. 
// 
 
NTSTATUS Usb2303Device::OnStopDevice(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Usb2303Device::OnStopDevice\n"; 
 
	m_Lower.DeActivateConfiguration(); 
 
 
// TODO:	Add device-specific code to stop your device    
 
	return status; 
	 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::OnRemoveDevice 
// 
//	Routine Description: 
//		Handler for IRP_MJ_PNP subfcn IRP_MN_REMOVE_DEVICE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		The system calls this when the device is removed. 
//		Our PnP policy will take care of  
//			(1) giving the IRP to the lower device 
//			(2) detaching the PDO 
//			(3) deleting the device object 
// 
 
NTSTATUS Usb2303Device::OnRemoveDevice(KIrp I) 
{ 
	t << "Entering Usb2303Device::OnRemoveDevice\n"; 
 
	// Device removed, release the system resources used by the USB lower device. 
	m_Lower.ReleaseResources(); 
 
 
// TODO:	Add device-specific code to remove your device    
 
	return STATUS_SUCCESS; 
 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::OnDevicePowerUp 
// 
//	Routine Description: 
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER 
//		for a request to go to power on state from low power state 
// 
//	Parameters: 
//		I - IRP containing POWER request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the OnDevicePowerUp function. 
//		This function was called by the framework from the completion 
//		routine of the IRP_MJ_POWER dispatch handler in KPnpDevice. 
//		The bus driver has completed the IRP and this driver can now 
//		access the hardware device.   
//		This routine runs at dispatch level. 
//	 
 
NTSTATUS Usb2303Device::OnDevicePowerUp(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Usb2303Device::OnDevicePowerUp\n"; 
 
// TODO:	Service the device. 
//			Restore any context to the hardware device that 
//			was saved during the handling of a power down request. 
//			See the OnDeviceSleep function. 
//			Do NOT complete this IRP. 
// 
	return status; 
 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::OnDeviceSleep 
// 
//	Routine Description: 
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER 
//		for a request to go to a low power state from a high power state 
// 
//	Parameters: 
//		I - IRP containing POWER request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the OnDeviceSleep function. 
//		This function was called by the framework from the IRP_MJ_POWER  
//		dispatch handler in KPnpDevice prior to forwarding to the PDO. 
//		The hardware has yet to be powered down and this driver can now 
//		access the hardware device.   
//		This routine runs at passive level. 
//	 
 
NTSTATUS Usb2303Device::OnDeviceSleep(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Usb2303Device::OnDeviceSleep\n"; 
 
// TODO:	Service the device. 
//			Save any context to the hardware device that will be required  
//			during a power up request. See the OnDevicePowerUp function. 
//			Do NOT complete this IRP.  The base class handles forwarding 
//			this IRP to the PDO. 
// 
	return status; 
 
	// The following macro simply allows compilation at Warning Level 4 
	// If you reference this parameter in the function simply remove the macro. 
	UNREFERENCED_PARAMETER(I); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::Create 
// 
//	Routine Description: 
//		Handler for IRP_MJ_CREATE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
// 
 
NTSTATUS Usb2303Device::Create(KIrp I) 
{ 
	NTSTATUS status; 
 
	t << "Entering Usb2303Device::Create, " << I << EOL; 
 
// TODO: Add driver specific create handling code here 
 
	// Generally a create IRP is targeted at our FDO, so we don't need 
	// to pass it down to the PDO.  We have found for some devices, the 
	// PDO is not expecting this Irp and returns an error code. 
	// The default wizard code, therefore completes the Irp here using 
	// PnpComplete().  The following commented code could be used instead 
	// of PnpComplete() to pass the Irp to the PDO, which would complete it. 
	// 
//	I.ForceReuseOfCurrentStackLocationInCalldown(); 
//	status = m_Lower.PnpCall(this, I); 
 
	status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT); 
 
	t << "Usb2303Device::Create Status " << (ULONG)status << EOL; 
 
	return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::Close 
// 
//	Routine Description: 
//		Handler for IRP_MJ_CLOSE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
// 
 
NTSTATUS Usb2303Device::Close(KIrp I) 
{ 
	NTSTATUS status; 
 
	t << "Entering Usb2303Device::Close, " << I << EOL; 
 
// TODO: Add driver specific close handling code here 
 
	// Generally a close IRP is targeted at our FDO, so we don't need 
	// to pass it down to the PDO.  We have found for some devices, the 
	// PDO is not expecting this Irp and returns an error code. 
	// The default wizard code, therefore completes the Irp here using 
	// PnpComplete().  The following commented code could be used instead 
	// of PnpComplete() to pass the Irp to the PDO, which would complete it. 
	// 
//	I.ForceReuseOfCurrentStackLocationInCalldown(); 
//	status = m_Lower.PnpCall(this, I); 
 
	status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT); 
 
	t << "Usb2303Device::Close Status " << (ULONG)status << EOL; 
 
    return status; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::Cleanup 
// 
//	Routine Description: 
//		Handler for IRP_MJ_CLEANUP	 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
// 
 
NTSTATUS Usb2303Device::CleanUp(KIrp I) 
{ 
	t << "Entering CleanUp, " << I << EOL; 
 
// TODO:	Insert your code to respond to the CLEANUP message. 
	return I.PnpComplete(this, STATUS_SUCCESS); 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::Read 
// 
//	Routine Description: 
//		Handler for IRP_MJ_READ 
// 
//	Parameters: 
//		I			Current IRP 
// 
//	Return Value: 
//		NTSTATUS	Result code 
// 
//	Comments: 
//		This routine handles read requests. 
// 
//		The KPnpDevice class handles restricting IRP flow 
//		if the device is stopping or being removed. 
// 
 
NTSTATUS Usb2303Device::Read(KIrp I)  
{ 
	t << "Entering Usb2303Device::Read, " << I << EOL; 
// TODO:	Check the incoming request.  Replace "FALSE" in the following 
//			line with a check that returns TRUE if the request is not valid. 
 
    if (FALSE)		// If (Request is invalid) 
	{ 
		// Invalid parameter in the Read request 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INVALID_PARAMETER); 
	} 
 
	// Always ok to read 0 elements. 
	if (I.ReadSize() == 0) 
	{ 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_SUCCESS); 
	} 
	NTSTATUS status		= STATUS_SUCCESS; 
 
	KMemory Mem(I.Mdl());						// Declare a memory object 
	// Use the memory object to create a pointer to the caller's buffer 
	PUCHAR	pBuffer		= (PUCHAR) Mem.VirtualAddress(); 
 
	ULONG   dwTotalSize = I.ReadSize(CURRENT);	// Requested read size 
	ULONG   dwBytesRead = 0;					// Count of bytes read 
 
// TODO:	If the read can be satisfied immediately, set the Information 
//			and Status fields now, then call NextIrp to complete this IRP 
//			and start processing the next IRP in the queue. 
 
// TODO:	If the data is not yet available, initiate a request to the 
//			physical device here, and defer the Information, Status, 
//			and NextIrp handling until the hardware indicates that the 
//			read is complete.  Typically, this might be handled in a 
//			DPC that is called after the hardware finishes transferring 
//			the data. 
 
// TODO:	To satisfy the read now, transfer data from the device to 
//			caller's buffer at "pBuffer".  Then, indicate how much data was 
//			transferred: 
 
	I.Information() = dwBytesRead; 
 
	return I.PnpComplete(this, status); 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::Write 
// 
//	Routine Description: 
//		Handler for IRP_MJ_WRITE 
// 
//	Parameters: 
//		I - Current IRP 
// 
//	Return Value: 
//		NTSTATUS - Result code 
// 
//	Comments: 
//		This routine handles write requests. 
// 
//		The KPnpDevice class handles restricting IRP flow 
//		if the device is stopping or being removed. 
// 
 
NTSTATUS Usb2303Device::Write(KIrp I)  
{ 
	t << "Entering Usb2303Device::Write, " << I << EOL; 
// TODO:	Check the incoming request.  Replace "FALSE" in the following 
//			line with a check that returns TRUE if the request is not valid. 
    if (FALSE) 
	{ 
		// Invalid parameter in the Write request 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_INVALID_PARAMETER); 
	} 
 
	// Always ok to write 0 elements. 
	if (I.WriteSize() == 0) 
	{ 
		I.Information() = 0; 
		return I.PnpComplete(this, STATUS_SUCCESS); 
	} 
	NTSTATUS status		= STATUS_SUCCESS; 
 
	KMemory Mem(I.Mdl());						// Declare a memory object 
	// Use the memory object to create a pointer to the caller's buffer 
	PUCHAR	pBuffer		= (PUCHAR) Mem.VirtualAddress(); 
 
	ULONG   dwTotalSize = I.WriteSize(CURRENT); 
	ULONG   dwBytesSent = 0; 
 
// TODO:	If the write can be satisfied immediately, set the Information 
//			and Status fields now, then call NextIrp to complete this IRP 
//			and start processing the next IRP in the queue. 
 
// TODO:	If the device cannot accept all of the data yet, initiate a  
//			request to the physical device here, and defer the Information, 
//			Status, and NextIrp handling until the hardware indicates that 
//			the write is complete.  Typically, this might be handled in a 
//			DPC that is called after the hardware finishes transferring 
//			the data. 
 
// TODO:	To satisfy the write now, transfer data to the device 
//			from caller's buffer at "pBuffer".  Then, indicate how much 
//			data was transferred: 
 
	I.Information() = dwBytesSent; 
 
	return I.PnpComplete(this, status); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::DeviceControl 
// 
//	Routine Description: 
//		Handler for IRP_MJ_DEVICE_CONTROL 
// 
//	Parameters: 
//		I - Current IRP 
//  
//	Return Value: 
//		None 
// 
//	Comments: 
//		This routine is the first handler for Device Control requests. 
//		The KPnpDevice class handles restricting IRP flow 
//		if the device is stopping or being removed. 
// 
 
NTSTATUS Usb2303Device::DeviceControl(KIrp I)  
{ 
	NTSTATUS status; 
 
	t << "Entering Usb2303Device::Device Control, " << I << EOL; 
	switch (I.IoctlCode()) 
	{ 
		case USB2303_IOCTL_Test: 
			status = USB2303_IOCTL_Test_Handler(I); 
			break; 
 
		default: 
			// Unrecognized IOCTL request 
			status = STATUS_INVALID_PARAMETER; 
			break; 
	} 
 
	// If the IRP's IOCTL handler deferred processing using some driver 
	// specific scheme, the status variable is set to STATUS_PENDING. 
	// In this case we simply return that status, and the IRP will be 
	// completed later.  Otherwise, complete the IRP using the status 
	// returned by the IOCTL handler. 
	if (status == STATUS_PENDING) 
	{ 
		return status; 
	} 
	else 
	{ 
		return I.PnpComplete(this, status); 
	} 
} 
 
//////////////////////////////////////////////////////////////////////// 
//  Usb2303Device::USB2303_IOCTL_Test_Handler 
// 
//	Routine Description: 
//		Handler for IO Control Code USB2303_IOCTL_Test 
// 
//	Parameters: 
//		I - IRP containing IOCTL request 
// 
//	Return Value: 
//		NTSTATUS - Status code indicating success or failure 
// 
//	Comments: 
//		This routine implements the USB2303_IOCTL_Test function. 
//		This routine runs at passive level. 
// 
 
NTSTATUS Usb2303Device::USB2303_IOCTL_Test_Handler(KIrp I) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	t << "Entering Usb2303Device::USB2303_IOCTL_Test_Handler, " << I << EOL; 
// TODO:	Verify that the input parameters are correct 
//			If not, return STATUS_INVALID_PARAMETER 
 
// TODO:	Handle the the USB2303_IOCTL_Test request, or  
//			defer the processing of the IRP (i.e. by queuing) and set 
//			status to STATUS_PENDING. 
 
// TODO:	Assuming that the request was handled here. Set I.Information 
//			to indicate how much data to copy back to the user. 
	I.Information() = 0; 
 
	return status; 
} 
 
 
 
void Usb2303Device::GetStringDescriptors() 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	PWCHAR String = (PWCHAR) new (NonPagedPool) WCHAR[MAXIMUM_USB_STRING_LENGTH]; 
 
	if(NULL == String) 
	{ 
		//error during allocation 
		t << "ERROR: Memory allocation error in GetStringDescriptors().\n"; 
		return; 
	} 
 
	t << "*****  PL2303 Device Descriptors  *****\n"; 
 
	USB_DEVICE_DESCRIPTOR desc; 
	status = m_Lower.GetDeviceDescriptor( &desc ); 
	if ( !NT_SUCCESS(status) ) 
	{ 
		t << "ERROR: Could not get Device Descriptor.\n"; 
		delete String; 
		return; 
	} 
 
 
	t << "Index of Manufacturer string = "	<< desc.bLength		<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.bDescriptorType		<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.bcdUSB		<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.bDeviceClass		<< "\n"; 
 
	t << "Index of Manufacturer string = "	<< desc.bDeviceSubClass	<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.bDeviceProtocol		<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.bMaxPacketSize0		<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.idVendor		<< "\n"; 
 
	t << "Index of Manufacturer string = "	<< desc.idProduct	<< "\n"; 
	t << "Index of Manufacturer string = "	<< desc.bcdDevice		<< "\n"; 
 
 
 
	t << "Index of Manufacturer string = "	<< desc.iManufacturer		<< "\n"; 
	t << "Index of Product string = "		<< desc.iProduct			<< "\n"; 
	t << "Index of Serial Number string = " << desc.iSerialNumber		<< "\n"; 
	t << "Number of configurations = "		<< desc.bNumConfigurations	<< "\n"; 
	t << "Index of configuration string = " << m_Lower.m_Config->iConfiguration << "\n"; 
 
 
	t << "*****  PL2303 Configuration Descriptors  *****\n"; 
 
	t << "Index of config string = "	<< m_Lower.m_Config->bLength		<< "\n"; 
	t << "Index of config string = "	<< m_Lower.m_Config->bDescriptorType		<< "\n"; 
	t << "Index of config string = "	<< m_Lower.m_Config->wTotalLength		<< "\n"; 
	t << "Index of config string = "	<< m_Lower.m_Config->bNumInterfaces 		<< "\n"; 
	t << "Index of config string = "	<< m_Lower.m_Config->iConfiguration		<< "\n"; 
	t << "Index of config string = "	<< m_Lower.m_Config->bmAttributes 		<< "\n"; 
	t << "Index of config string = "	<< m_Lower.m_Config->MaxPower 		<< "\n"; 
 
	t << "*****  PL2303 interface Descriptors  *****\n"; 
 
	t << "Index of interface string = "	<< m_Interface.m_Information->Length		<< "\n"; 
	t << "Index of interface string = "	<< m_Interface.m_Information->InterfaceNumber		<< "\n"; 
	t << "Index of interface string = "	<< m_Interface.m_Information->AlternateSetting 		<< "\n"; 
	t << "Index of interface string = "	<< m_Interface.m_Information->NumberOfPipes		<< "\n"; 
	t << "Index of interface string = "	<< m_Interface.m_Information->Class 		<< "\n"; 
	t << "Index of interface string = "	<< m_Interface.m_Information->SubClass 		<< "\n"; 
	t << "Index of interface string = "	<< m_Interface.m_Information->Protocol 		<< "\n"; 
 
	t << "*****  PL2303 Endpoint1IN Descriptors  *****\n"; 
 
	t << "Index of m_Endpoint1IN string->EndpointAddress = "	<< m_Endpoint1IN.m_EndpointAddress << "\n"; 
	t << "Index of m_Endpoint1IN string->MaximumPacketSize = "	<< m_Endpoint1IN.MaximumPacketSize() << "\n"; 
	t << "Index of m_Endpoint1IN string->PollInterval = "	<< m_Endpoint1IN.PollInterval()	<< "\n"; 
	t << "Index of m_Endpoint1IN string->PipeType = "	<< m_Endpoint1IN.Type()	<< "\n"; 
 
 
	t << "*****  PL2303 Endpoint2OUT Descriptors  *****\n"; 
 
	t << "Index of m_Endpoint2OUT string->EndpointAddress = "	<< m_Endpoint2OUT.m_EndpointAddress << "\n"; 
	t << "Index of m_Endpoint2OUT string->MaximumPacketSize = "	<< m_Endpoint2OUT.MaximumPacketSize() << "\n"; 
	t << "Index of m_Endpoint2OUT string->PollInterval = "	<< m_Endpoint2OUT.PollInterval()	<< "\n"; 
	t << "Index of m_Endpoint2OUT string->PipeType = "	<< m_Endpoint2OUT.Type()	<< "\n"; 
 
	t << "*****  PL2303 Endpoint3IN Descriptors  *****\n"; 
 
	t << "Index of m_Endpoint3IN string->EndpointAddress = "	<< m_Endpoint3IN.m_EndpointAddress << "\n"; 
	t << "Index of m_Endpoint3IN string->MaximumPacketSize = "	<< m_Endpoint3IN.MaximumPacketSize() << "\n"; 
	t << "Index of m_Endpoint3IN string->PollInterval = "	<< m_Endpoint3IN.PollInterval()	<< "\n"; 
	t << "Index of m_Endpoint3IN string->PipeType = "	<< m_Endpoint3IN.Type()	<< "\n"; 
 
 
	t << "*****  PL2303 String Descriptors  *****\n"; 
 
	for(UCHAR i = 0; i <= NUM_STRING_DESCRIPTORS; i++) 
	{ 
		RtlZeroMemory(String, MAXIMUM_USB_STRING_LENGTH * sizeof(WCHAR)); 
 
		if(NT_SUCCESS(status = m_Lower.GetStringDescriptor( 
														i,  
														String,  
														MAXIMUM_USB_STRING_LENGTH,  
														0x409))) 
		{ 
			t << "String " << i << ": " << String << "\n"; 
		} 
		else 
		{ 
			t << "GetStringDescriptor returns status = " << ULONG(status) << "\n"; 
		} 
	} 
 
	t << "\n"; 
 
	delete String; 
 
 
 
 
 
}