www.pudn.com > disk-filter.gz > ioctl.c, change:2006-04-18,size:11116b


/*================================================================================== 
 
 
Module Name: 
 
  ioctl.c 
 
Description: 
  write for fruitprince 
 
Author: 
 
  wangxinguo 
 
Date&Time: 
 
  2006-03-12 
 
==================================================================================*/ 
 
#include <ntddk.h> 
#include "iocmd.h" 
#include "diskf_scu.h" 
 
// 
//Default value is TRUE. do not log 
// 
BOOLEAN  g_bLogDiskFlag = FALSE; 
 
// 
//Log list 
// 
//LIST_ENTRY  g_LogList; 
 
extern PDEVICE_OBJECT g_DiskfControlDeviceObject; 
extern PDRIVER_OBJECT g_DiskfDriverObject; 
 
extern NPAGED_LOOKASIDE_LIST g_ReadLookAsideList; 
extern FAST_MUTEX  g_LogBufferMutex; 
 
LOG_BUFFER  g_LogBuffer; 
 
 
NTSTATUS 
Diskf_ReadCompletion( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp, 
	IN PVOID Context 
	); 
 
VOID 
Diskf_WorkItemRoutine( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PVOID Context 
    ); 
 
NTSTATUS 
Diskf_DeviceControl( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP           Irp 
	) 
{ 
	NTSTATUS  status; 
 
	if( DeviceObject == g_DiskfControlDeviceObject ) 
	{	 
		status = Diskf_DeviceControlCDO( DeviceObject, Irp ); 
		 
		return status; 
	} 
	else 
	{		 
		status =DiskPerfDeviceControl( DeviceObject, Irp ); 
		 
		return status; 
	} 
} 
 
 
NTSTATUS 
Diskf_DeviceControlCDO(  
	IN  PDEVICE_OBJECT  DeviceObject, 
	IN  PIRP            Irp 
	) 
{ 
	NTSTATUS status = STATUS_SUCCESS; 
 
	PIO_STACK_LOCATION  irpStack; 
	PVOID               inputBuffer; 
	PVOID               outputBuffer; 
	ULONG               inputBufferLength; 
	ULONG               outputBufferLength; 
	ULONG               ioControlCode; 
	 
	// 
	// Go ahead and set the request up as successful 
	// 
	Irp->IoStatus.Status      = STATUS_SUCCESS; 
	Irp->IoStatus.Information = 0; 
	 
	// 
	// Get a pointer to the current location in the Irp. This is where 
	// the function codes and parameters are located. 
	// 
	irpStack = IoGetCurrentIrpStackLocation (Irp); 
	 
	// 
	// Get the pointer to the input/output buffer and its length 
	// 
	inputBuffer        = Irp->AssociatedIrp.SystemBuffer; 
	inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength; 
	outputBuffer       = Irp->AssociatedIrp.SystemBuffer; 
	outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; 
	ioControlCode      = irpStack->Parameters.DeviceIoControl.IoControlCode; 
 
	switch( ioControlCode ) 
	{ 
	case IOCTL_DISKF_DUMP_PARAMETER: 
		{ 
			//#define  MAX_LOG_BUFFER_SIZE  1024*64 // 64KB 
			//#define  MAX_LOG_ENTRY_COUNT  (MAX_LOG_BUFFER_SIZE / sizeof(LOG_ENTRY))  
			KdPrint(("Diskf_DeviceControlCDO: Log buffer size = %d,entry count = %d\n", 
				      MAX_LOG_BUFFER_SIZE, 
                      MAX_LOG_ENTRY_COUNT 
					  )); 
 
			KdPrint(("Diskf_DeviceControlCDO:g_LogBuffer.EntryCount=%d,g_LogBuffer.Buffer=0x%08x\n", 
				      g_LogBuffer.EntryCount,  
					  g_LogBuffer.Buffer)); 
 
			Irp->IoStatus.Information = 2; // 2 is magic number.just for test 
		} 
		break; 
 
	case IOCTL_DISKF_SET_CONTROL_FLAG: 
		 if( ( inputBuffer == NULL ) || ( inputBufferLength != 1 ) ) 
		 { 
			 status = STATUS_INVALID_PARAMETER;			  
		 } 
		 else if( g_LogBuffer.Buffer == NULL ) 
		 { 
			 // 
			 //Allocate Memory failure 
			 // 
			 status = STATUS_NO_MEMORY; 
		 } 
		 else 
		 { 
			 g_bLogDiskFlag =  *(BOOLEAN*)inputBuffer; 
 
			 KdPrint(("Diskf_DeviceControlCDO: g_bLogDiskFlag = %d\n",    
				       g_bLogDiskFlag)); 
 
			 if( g_bLogDiskFlag == FALSE ) 
			 { 
				 ExAcquireFastMutex(&g_LogBufferMutex); 
				 g_LogBuffer.EntryCount = 0; 
				 ExReleaseFastMutex(&g_LogBufferMutex); 
			 } 
		 } 
		break; 
 
	case IOCTL_DISKF_GET_LOG_BUFFER: 
		{ 
	 
			outputBuffer = Irp->UserBuffer; 
			 
			// 
			//check output buffer size 
			// 
			if( MAX_LOG_BUFFER_SIZE > outputBufferLength ) 
			{ 
				status = STATUS_BUFFER_TOO_SMALL; 
				break; 
			} 
			 
            // 
            // Probe the output buffer 
            // 
            try  
			{   
				 
				KdPrint(("Diskf_DeviceControlCDO:outputBuffer = 0x%08x,outputBufferLen= %d\n", 
					      outputBuffer, 
						  outputBufferLength 
						  )); 
 
                ProbeForWrite( outputBuffer, 
                               outputBufferLength, 
                               sizeof( UCHAR )); 
 
            } 
			except( EXCEPTION_EXECUTE_HANDLER )  
			{ 
                status = STATUS_INVALID_PARAMETER; 
				KdPrint(("Diskf_DeviceControlCDO:Exception code = 0x%08x\n",  
					      GetExceptionCode( ) 
						  )); 
                break; 
            }   
  
			// 
			//copy memory to user buffer 
			// 
			ExAcquireFastMutex(&g_LogBufferMutex); 
 
			RtlCopyMemory( outputBuffer,  
				           g_LogBuffer.Buffer, 
						   g_LogBuffer.EntryCount * sizeof( LOG_ENTRY) 
						   ); 
 
            Irp->IoStatus.Information = g_LogBuffer.EntryCount; 
			g_LogBuffer.EntryCount = 0; 
 
			ExReleaseFastMutex(&g_LogBufferMutex); 
		} 
		break; 
 
	case IOCTL_DISKF_GET_LOG_COUNT: 
 
		ExAcquireFastMutex(&g_LogBufferMutex);		 
		Irp->IoStatus.Information = g_LogBuffer.EntryCount;		 
		ExReleaseFastMutex(&g_LogBufferMutex); 
		break; 
 
	default: 
		break; 
 
	} 
 
	Irp->IoStatus.Status = status;	 
	IoCompleteRequest( Irp, IO_NO_INCREMENT ); 
 
	return status; 
} 
 
 
NTSTATUS 
Diskf_Close( 
   IN PDEVICE_OBJECT  DeviceObject, 
   IN PIRP            Irp 
   ) 
{ 
	NTSTATUS  status; 
 
	if( DeviceObject == g_DiskfControlDeviceObject ) 
	{	 
		g_bLogDiskFlag = FALSE; 
 
		Irp->IoStatus.Status = STATUS_SUCCESS; 
		Irp->IoStatus.Information = 0; 
		 
		IoCompleteRequest( Irp, IO_NO_INCREMENT ); 
		 
		return STATUS_SUCCESS; 
	} 
	else 
	{		 
		status =DiskPerfSendToNextDriver( DeviceObject, Irp ); 
		 
		return status; 
	} 
} 
 
NTSTATUS 
Diskf_Read( 
   IN PDEVICE_OBJECT  DeviceObject, 
   IN PIRP            Irp 
   ) 
/*++ 
 Notes: 
    When golbal variable g_bLogDiskFlag == TRUE, 
	This routine will be called! 
--*/ 
{ 
	PDEVICE_EXTENSION  DevExt = DeviceObject->DeviceExtension; 
 
	IoCopyCurrentIrpStackLocationToNext(Irp); 
	IoSetCompletionRoutine(Irp, Diskf_ReadCompletion, NULL, TRUE, TRUE,TRUE); 
	 
	return IoCallDriver(DevExt->TargetDeviceObject, Irp); 
} 
 
 
VOID 
Diskf_Write( 
   IN PDEVICE_OBJECT  DeviceObject, 
   IN PIRP            Irp 
   ) 
/*++ 
 Notes: 
    When golbal variable g_bLogDiskFlag == TRUE, 
	This routine will be called! 
--*/ 
{ 
	PDEVICE_EXTENSION  DevExt = DeviceObject->DeviceExtension; 
	PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp ); 
 
	// 
	//Length. (in sectors) 
	// 
	ULONG      Length = irpStack->Parameters.Write.Length / 512; 
	// 
	//ByteIndex. ( in bytes) 
	// 
	ULONGLONG  ByteIndex = irpStack->Parameters.Write.ByteOffset.QuadPart; 
	// 
	//SectorIndex. ( in Sector) 
	// 
	ULONG  SectorIndex = (ULONG)( ByteIndex / 512 ); 
 
	 
	PLOG_ENTRY LogEntry = NULL; 
 
    PCHAR  Data; 
 
	if (Irp->MdlAddress) 
		Data = MmGetSystemAddressForMdl(Irp->MdlAddress); 
	else  
		Data = Irp->UserBuffer; 
 
	if( Data == NULL) 
	{ 
		return; 
	} 
 
	ExAcquireFastMutex(&g_LogBufferMutex); 
	if( g_LogBuffer.EntryCount >= MAX_LOG_ENTRY_COUNT ) 
	{ 
		ExReleaseFastMutex(&g_LogBufferMutex); 
		return; 
	} 
 
    LogEntry =(PLOG_ENTRY) (g_LogBuffer.Buffer + (g_LogBuffer.EntryCount*8)); 
 
	LogEntry->DiskNumber = DevExt->DiskNumber; 
	LogEntry->Length = Length; 
	LogEntry->OperationType = 1; 
	LogEntry->SectorNumber =SectorIndex; 
 
	RtlCopyMemory(LogEntry->Data, Data, 16 ); 
 
	g_LogBuffer.EntryCount++; 
	ExReleaseFastMutex(&g_LogBufferMutex); 
} 
 
NTSTATUS 
Diskf_ReadCompletion( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp, 
	IN PVOID Context 
	) 
/*++ 
  Notes: 
    Thread Context == arbitrary thread or DPC context 
	IRQL           == from PASSIVE_LEVEL to DISPATCH_LEVEL 
 
--*/ 
{ 
	PDEVICE_EXTENSION  DevExt = DeviceObject->DeviceExtension; 
	PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp ); 
	// 
	//Length. (in sectors) 
	// 
	ULONG      Length = irpStack->Parameters.Read.Length / 512; 
	// 
	//ByteIndex. ( in bytes) 
	// 
	ULONGLONG  ByteIndex = irpStack->Parameters.Read.ByteOffset.QuadPart; 
	// 
	//SectorIndex. ( in Sector) 
	// 
	ULONG      SectorIndex = (ULONG)( ByteIndex / 512 ); 
	PLOG_ENTRY LogEntry = NULL; 
 
	PCHAR  Data; 
	 
	if (Irp->MdlAddress) 
		Data = MmGetSystemAddressForMdl(Irp->MdlAddress); 
	else  
		Data = Irp->UserBuffer;	 
	if( Data == NULL) 
	{ 
		return STATUS_SUCCESS; 
	} 
 
	if (Irp->PendingReturned) 
		IoMarkIrpPending(Irp); 
 
	if( KeGetCurrentIrql() == DISPATCH_LEVEL )  
	{ 
		PIO_WORKITEM        WorkItem; 
		PWORK_ITEM_CONTEXT  WorkItemContext; 
 
		WorkItemContext = ExAllocateFromNPagedLookasideList( &g_ReadLookAsideList );	 
		if( WorkItemContext == NULL) 
			return STATUS_SUCCESS; 
 
        WorkItemContext->Log.DiskNumber = DevExt->DiskNumber; 
		WorkItemContext->Log.Length     = Length; 
		WorkItemContext->Log.OperationType = 0; //0 is Read 
		WorkItemContext->Log.SectorNumber = SectorIndex; 
 
		RtlCopyMemory(WorkItemContext->Log.Data, Data, 16 ); 
 
		WorkItem = IoAllocateWorkItem( DeviceObject ); 
		WorkItemContext->WorkItem = WorkItem; 
 
		if( WorkItem == NULL ) 
			return STATUS_SUCCESS; 
 
		IoQueueWorkItem( WorkItem, 
			             Diskf_WorkItemRoutine, 
						 CriticalWorkQueue,  
						 WorkItemContext 
						 ); 
 
		return STATUS_SUCCESS; 
	} 
	else 
	{		 
		ExAcquireFastMutex(&g_LogBufferMutex); 
		if( g_LogBuffer.EntryCount >= MAX_LOG_ENTRY_COUNT ) 
		{ 
		// 
		//Out of memory.we can not log this request 
		// 
			ExReleaseFastMutex(&g_LogBufferMutex); 
			return STATUS_SUCCESS; 
		} 
		 
		LogEntry =(PLOG_ENTRY) (g_LogBuffer.Buffer + (g_LogBuffer.EntryCount*8)); 
		 
		LogEntry->DiskNumber = DevExt->DiskNumber; 
		LogEntry->Length = Length; 
		LogEntry->OperationType = 0; 
		LogEntry->SectorNumber =SectorIndex; 
		 
		RtlCopyMemory(LogEntry->Data, Data, 16 ); 
		 
		g_LogBuffer.EntryCount++; 
		 
		ExReleaseFastMutex(&g_LogBufferMutex); 
	} 
	return STATUS_SUCCESS; 
} 
 
VOID 
Diskf_WorkItemRoutine( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PVOID Context 
    ) 
{ 
	PWORK_ITEM_CONTEXT  WorkItemContext; 
	PLOG_ENTRY      LogEntry; 
 
	WorkItemContext = (PWORK_ITEM_CONTEXT)Context; 
	IoFreeWorkItem( WorkItemContext->WorkItem ); 
 
	ExAcquireFastMutex(&g_LogBufferMutex); 
	if( g_LogBuffer.EntryCount >= MAX_LOG_ENTRY_COUNT ) 
	{ 
		// 
		//Out of memory.we can not log this request 
		// 
		ExReleaseFastMutex(&g_LogBufferMutex); 
		ExFreeToNPagedLookasideList(&g_ReadLookAsideList, WorkItemContext); 
		return; 
	} 
 
    LogEntry =(PLOG_ENTRY) (g_LogBuffer.Buffer + (g_LogBuffer.EntryCount*8)); 
 
	LogEntry->DiskNumber    = WorkItemContext->Log.DiskNumber; 
	LogEntry->Length        = WorkItemContext->Log.Length; 
	LogEntry->OperationType = WorkItemContext->Log.OperationType; 
	LogEntry->SectorNumber  = WorkItemContext->Log.SectorNumber; 
 
	RtlCopyMemory(LogEntry->Data, 
		          WorkItemContext->Log.Data,  
				  16 ); 
 
	g_LogBuffer.EntryCount++; 
 
	ExReleaseFastMutex(&g_LogBufferMutex); 
	ExFreeToNPagedLookasideList(&g_ReadLookAsideList, WorkItemContext); 
}