www.pudn.com > WDM_Driver_Dev_ExampleCode.zip > Dispatch.cpp


////////////////////////////////////////////////////////////////////////////// 
//	Copyright © 1998 Chris Cant, PHD Computer Consultants Ltd 
//	WDM Book for R&D Books, Miller Freeman Inc 
// 
//	Wdm1 example 
///////////////////////////////////////////////////////////////////////////// 
//	dispatch.cpp:	Other IRP handlers 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1Create			Handle Create/Open file IRP 
//	Wdm1Close			Handle Close file IRPs 
//	Wdm1Read			Handle Read IRPs 
//	Wdm1Write			Handle Write IRPs 
//	Wdm1DeviceControl	Handle DeviceIoControl IRPs 
//	Wdm1SystemControl	Handle WMI IRPs 
///////////////////////////////////////////////////////////////////////////// 
//	Version history 
//	27-Apr-99	1.0.0	CC	creation 
///////////////////////////////////////////////////////////////////////////// 
 
#include "wdm1.h" 
#include "Ioctl.h" 
 
///////////////////////////////////////////////////////////////////////////// 
///////////////////////////////////////////////////////////////////////////// 
//	Buffer and BufferSize and guarding spin lock globals (in unpaged memory) 
 
KSPIN_LOCK BufferLock; 
PUCHAR	Buffer = NULL; 
ULONG	BufferSize = 0; 
 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1Create: 
// 
//	Description: 
//		Handle IRP_MJ_CREATE requests 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
//			IrpStack->Parameters.Create.xxx has create parameters 
//			IrpStack->FileObject->FileName has file name of device 
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
NTSTATUS Wdm1Create(	IN PDEVICE_OBJECT fdo, 
					IN PIRP Irp) 
{ 
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); 
	DebugPrint( "Create File is %T", &(IrpStack->FileObject->FileName)); 
 
	// Complete successfully 
	return CompleteIrp(Irp,STATUS_SUCCESS,0); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1Close: 
// 
//	Description: 
//		Handle IRP_MJ_CLOSE requests 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
NTSTATUS Wdm1Close(	IN PDEVICE_OBJECT fdo, 
					IN PIRP Irp) 
{ 
	DebugPrintMsg("Close"); 
 
	// Complete successfully 
	return CompleteIrp(Irp,STATUS_SUCCESS,0); 
} 
  
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1Read: 
// 
//	Description: 
//		Handle IRP_MJ_READ requests 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
//			IrpStack->Parameters.Read.xxx has read parameters 
//			User buffer at:	AssociatedIrp.SystemBuffer	(buffered I/O) 
//							MdlAddress					(direct I/O) 
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
NTSTATUS Wdm1Read(IN PDEVICE_OBJECT fdo, 
				  IN PIRP Irp) 
{ 
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); 
	NTSTATUS status = STATUS_SUCCESS; 
	LONG BytesTxd = 0; 
 
	// Get call parameters 
	LONGLONG FilePointer = IrpStack->Parameters.Read.ByteOffset.QuadPart; 
	ULONG ReadLen = IrpStack->Parameters.Read.Length; 
	DebugPrint("Read %d bytes from file pointer %d",(int)ReadLen,(int)FilePointer); 
 
	// Get access to the shared buffer 
	KIRQL irql; 
	KeAcquireSpinLock(&BufferLock,&irql); 
 
	// Check file pointer 
	if( FilePointer<0) 
		status = STATUS_INVALID_PARAMETER; 
	if( FilePointer>=(LONGLONG)BufferSize) 
		status = STATUS_END_OF_FILE; 
 
	if( status==STATUS_SUCCESS) 
	{ 
		// Get transfer count 
		if( ((ULONG)FilePointer)+ReadLen>BufferSize) 
		{ 
			BytesTxd = BufferSize - (ULONG)FilePointer; 
			if( BytesTxd<0) BytesTxd = 0; 
		} 
		else 
			BytesTxd = ReadLen; 
 
		// Read from shared buffer 
		if( BytesTxd>0 && Buffer!=NULL) 
			RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, Buffer+FilePointer, BytesTxd); 
	} 
 
	// Release shared buffer 
	KeReleaseSpinLock(&BufferLock,irql); 
 
	DebugPrint("Read: %d bytes returned",(int)BytesTxd); 
 
	// Complete IRP 
	return CompleteIrp(Irp,status,BytesTxd); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1Write: 
// 
//	Description: 
//		Handle IRP_MJ_WRITE requests 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
//			IrpStack->Parameters.Write.xxx has write parameters 
//			User buffer at:	AssociatedIrp.SystemBuffer	(buffered I/O) 
//							MdlAddress					(direct I/O) 
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
NTSTATUS Wdm1Write(	IN PDEVICE_OBJECT fdo, 
					IN PIRP Irp) 
{ 
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); 
	NTSTATUS status = STATUS_SUCCESS; 
	LONG BytesTxd = 0; 
 
	// Get call parameters 
	LONGLONG FilePointer = IrpStack->Parameters.Write.ByteOffset.QuadPart; 
	ULONG WriteLen = IrpStack->Parameters.Write.Length; 
	DebugPrint("Write %d bytes from file pointer %d",(int)WriteLen,(int)FilePointer); 
 
	if( FilePointer<0) 
		status = STATUS_INVALID_PARAMETER; 
	else 
	{ 
		// Get access to the shared buffer 
		KIRQL irql; 
		KeAcquireSpinLock(&BufferLock,&irql); 
 
		BytesTxd = WriteLen; 
 
		// (Re)allocate buffer if necessary 
		if( ((ULONG)FilePointer)+WriteLen>BufferSize) 
		{ 
			ULONG NewBufferSize = ((ULONG)FilePointer)+WriteLen; 
			PVOID NewBuffer = ExAllocatePool(NonPagedPool,NewBufferSize); 
			if( NewBuffer==NULL) 
			{ 
				BytesTxd = BufferSize - (ULONG)FilePointer; 
				if( BytesTxd<0) BytesTxd = 0; 
			} 
			else 
			{ 
				RtlZeroMemory(NewBuffer,NewBufferSize); 
				if( Buffer!=NULL) 
				{ 
					RtlCopyMemory(NewBuffer,Buffer,BufferSize); 
					ExFreePool(Buffer); 
				} 
				Buffer = (PUCHAR)NewBuffer; 
				BufferSize = NewBufferSize; 
			} 
		} 
 
		// Write to shared memory 
		if( BytesTxd>0 && Buffer!=NULL) 
			RtlCopyMemory( Buffer+FilePointer, Irp->AssociatedIrp.SystemBuffer, BytesTxd); 
 
		// Release shared buffer 
		KeReleaseSpinLock(&BufferLock,irql); 
	} 
 
	DebugPrint("Write: %d bytes written",(int)BytesTxd); 
 
	// Complete IRP 
	return CompleteIrp(Irp,status,BytesTxd); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1DeviceControl: 
// 
//	Description: 
//		Handle IRP_MJ_DEVICE_CONTROL requests 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
//			Buffered:	AssociatedIrp.SystemBuffer (and IrpStack->Parameters.DeviceIoControl.Type3InputBuffer) 
//			Direct:		MdlAddress 
// 
//			IrpStack->Parameters.DeviceIoControl.InputBufferLength 
//			IrpStack->Parameters.DeviceIoControl.OutputBufferLength  
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
NTSTATUS Wdm1DeviceControl(	IN PDEVICE_OBJECT fdo, 
							IN PIRP Irp) 
{ 
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); 
	NTSTATUS status = STATUS_SUCCESS; 
	ULONG BytesTxd = 0; 
 
	ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; 
	ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; 
	ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
 
	DebugPrint("DeviceIoControl: Control code %x InputLength %d OutputLength %d", 
				ControlCode, InputLength, OutputLength); 
 
	// Get access to the shared buffer 
	KIRQL irql; 
	KeAcquireSpinLock(&BufferLock,&irql); 
	switch( ControlCode) 
	{ 
	///////	Zero Buffer 
	case IOCTL_WDM1_ZERO_BUFFER: 
		// Zero the buffer 
		if( Buffer!=NULL && BufferSize>0) 
			RtlZeroMemory(Buffer,BufferSize); 
		break; 
 
	///////	Remove Buffer 
	case IOCTL_WDM1_REMOVE_BUFFER: 
		if( Buffer!=NULL) 
		{ 
			ExFreePool(Buffer); 
			Buffer = NULL; 
			BufferSize = 0; 
		} 
		break; 
 
	///////	Get Buffer Size as ULONG 
	case IOCTL_WDM1_GET_BUFFER_SIZE: 
		if( OutputLengthAssociatedIrp.SystemBuffer,&BufferSize,sizeof(ULONG)); 
		} 
		break; 
 
	///////	Get Buffer 
	case IOCTL_WDM1_GET_BUFFER: 
		if( OutputLength>BufferSize) 
			status = STATUS_INVALID_PARAMETER; 
		else 
		{ 
			BytesTxd = OutputLength; 
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,Buffer,BytesTxd); 
		} 
		break; 
 
	///////	Invalid request 
	default: 
		status = STATUS_INVALID_DEVICE_REQUEST; 
	} 
	// Release shared buffer 
	KeReleaseSpinLock(&BufferLock,irql); 
 
	DebugPrint("DeviceIoControl: %d bytes written",(int)BytesTxd); 
 
	// Complete IRP 
	return CompleteIrp(Irp,status,BytesTxd); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1SystemControl: 
// 
//	Description: 
//		Handle IRP_MJ_SYSTEM_CONTROL requests 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
//			Various minor parameters 
//			IrpStack->Parameters.WMI.xxx has WMI parameters 
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
NTSTATUS Wdm1SystemControl(	IN PDEVICE_OBJECT fdo, 
							IN PIRP Irp) 
{ 
	DebugPrintMsg("SystemControl"); 
 
	// Just pass to lower driver 
	IoSkipCurrentIrpStackLocation(Irp); 
	PWDM1_DEVICE_EXTENSION dx = (PWDM1_DEVICE_EXTENSION)fdo->DeviceExtension; 
	return IoCallDriver( dx->NextStackDevice, Irp); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
//	Wdm1Cleanup: 
// 
//	Description: 
//		Handle IRP_MJ_CLEANUP requests 
//		Cancel queued IRPs which match given FileObject 
// 
//	Arguments: 
//		Pointer to our FDO 
//		Pointer to the IRP 
//			IrpStack->FileObject has handle to file 
// 
//	Return Value: 
//		This function returns STATUS_XXX 
 
//	Not needed for Wdm1 
 
///////////////////////////////////////////////////////////////////////////// 
//	CompleteIrp:	Sets IoStatus and completes the IRP 
 
NTSTATUS CompleteIrp( PIRP Irp, NTSTATUS status, ULONG info) 
{ 
	Irp->IoStatus.Status = status; 
	Irp->IoStatus.Information = info; 
	IoCompleteRequest(Irp,IO_NO_INCREMENT); 
	return status; 
} 
 
/////////////////////////////////////////////////////////////////////////////