📄 functions.c
字号:
Irp->IoStatus.Information = dwDataWritten;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_WriteNeither Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_ReadDirectIO
*
* This is called when a read is issued on the device handle (ReadFile/ReadFileEx)
*
* This version uses Direct I/O
*
**********************************************************************/
NTSTATUS Example_ReadDirectIO(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_BUFFER_TOO_SMALL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
UINT dwDataRead = 0;
PCHAR pReadDataBuffer;
DbgPrint("Example_ReadDirectIO Called \r\n");
/*
* Each time the IRP is passed down the driver stack a new stack location is added
* specifying certain parameters for the IRP to the driver.
*/
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
if(pIoStackIrp && Irp->MdlAddress)
{
pReadDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
if(pReadDataBuffer && pIoStackIrp->Parameters.Read.Length)
{
if(Example_ReadData((PEXAMPLE_LIST)pIoStackIrp->FileObject->FsContext, pReadDataBuffer, pIoStackIrp->Parameters.Read.Length, &dwDataRead))
{
NtStatus = STATUS_SUCCESS;
}
}
}
/*
* This does not always need to be completed in this manner. The I/O Manager is friendly
* and in the simple case (as this driver is implemented) the IRP will be completed
* by IoCompleteRequest() and the Status will be set to the return value.
*
* What will not be set however is the "Information" field, it cannot be set to how many bytes
* were read or written obviously because the I/O Manager does not know, only your device
* driver does.
*
* There are cases where you will need to complete the IRP and set the status however
* our simple driver does not require that.
*
* In the Write operation the "bytes written" is really only used as an informant to
* the application. The Read operation is a bit different. For example, some types of buffering
* it may not matter if you set the number of bytes read. For example "Neither" you write
* directly into the user mode buffer so the user mode gets the data even if you don't
* tell it the amount. However if you remember how buffered I/O works? It makes a copy
* in memory. If the I/O manager doesn't know the size then it can't copy it back to the
* user mode buffer.
*
*
* IO_NO_INCREMENT - What is this? If an IRP request is taking a long time you may want to help
* the scheduler to re-schedule the thread as soon as possible. For example perhaps it issued
* a network request and went to sleep. Then on another thread the network request completes
* You may want to use one of the pre-defined constants or your own to increment the priority of
* that thread to be rescheduled being since it hasn't been scheduled in a while.
*
*/
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = dwDataRead;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_ReadDirectIO Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_ReadBufferedIO
*
* This is called when a read is issued on the device handle (ReadFile/ReadFileEx)
*
* This version uses Buffered I/O
*
**********************************************************************/
NTSTATUS Example_ReadBufferedIO(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_BUFFER_TOO_SMALL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
UINT dwDataRead = 0;
PCHAR pReadDataBuffer;
DbgPrint("Example_ReadBufferedIO Called \r\n");
/*
* Each time the IRP is passed down the driver stack a new stack location is added
* specifying certain parameters for the IRP to the driver.
*/
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
if(pIoStackIrp)
{
pReadDataBuffer = (PCHAR)Irp->AssociatedIrp.SystemBuffer;
if(pReadDataBuffer && pIoStackIrp->Parameters.Read.Length > 0)
{
if(Example_ReadData((PEXAMPLE_LIST)pIoStackIrp->FileObject->FsContext, pReadDataBuffer, pIoStackIrp->Parameters.Read.Length, &dwDataRead))
{
NtStatus = STATUS_SUCCESS;
}
}
}
/*
* This does not always need to be completed in this manner. The I/O Manager is friendly
* and in the simple case (as this driver is implemented) the IRP will be completed
* by IoCompleteRequest() and the Status will be set to the return value.
*
* What will not be set however is the "Information" field, it cannot be set to how many bytes
* were read or written obviously because the I/O Manager does not know, only your device
* driver does.
*
* There are cases where you will need to complete the IRP and set the status however
* our simple driver does not require that.
*
* In the Write operation the "bytes written" is really only used as an informant to
* the application. The Read operation is a bit different. For example, some types of buffering
* it may not matter if you set the number of bytes read. For example "Neither" you write
* directly into the user mode buffer so the user mode gets the data even if you don't
* tell it the amount. However if you remember how buffered I/O works? It makes a copy
* in memory. If the I/O manager doesn't know the size then it can't copy it back to the
* user mode buffer.
*
*
* IO_NO_INCREMENT - What is this? If an IRP request is taking a long time you may want to help
* the scheduler to re-schedule the thread as soon as possible. For example perhaps it issued
* a network request and went to sleep. Then on another thread the network request completes
* You may want to use one of the pre-defined constants or your own to increment the priority of
* that thread to be rescheduled being since it hasn't been scheduled in a while.
*
*/
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = dwDataRead;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_ReadBufferedIO Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_ReadNeither
*
* This is called when a Read is issued on the device handle (ReadFile/ReadFileEx)
*
* This version uses Neither buffered or direct I/O. User mode memory is
* written directly.
*
**********************************************************************/
NTSTATUS Example_ReadNeither(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_BUFFER_TOO_SMALL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
UINT dwDataRead = 0;
PCHAR pReadDataBuffer;
DbgPrint("Example_ReadNeither Called \r\n");
/*
* Each time the IRP is passed down the driver stack a new stack location is added
* specifying certain parameters for the IRP to the driver.
*/
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
if(pIoStackIrp)
{
/*
* We need this in an exception handler or else we could trap.
*/
__try {
if(pIoStackIrp->Parameters.Read.Length > 0 && Irp->UserBuffer)
{
ProbeForWrite(Irp->UserBuffer, pIoStackIrp->Parameters.Read.Length, TYPE_ALIGNMENT(char));
pReadDataBuffer = Irp->UserBuffer;
if(Example_ReadData((PEXAMPLE_LIST)pIoStackIrp->FileObject->FsContext, pReadDataBuffer, pIoStackIrp->Parameters.Read.Length, &dwDataRead))
{
NtStatus = STATUS_SUCCESS;
}
}
} __except( EXCEPTION_EXECUTE_HANDLER ) {
NtStatus = GetExceptionCode();
}
}
/*
* This does not always need to be completed in this manner. The I/O Manager is friendly
* and in the simple case (as this driver is implemented) the IRP will be completed
* by IoCompleteRequest() and the Status will be set to the return value.
*
* What will not be set however is the "Information" field, it cannot be set to how many bytes
* were read or written obviously because the I/O Manager does not know, only your device
* driver does.
*
* There are cases where you will need to complete the IRP and set the status however
* our simple driver does not require that.
*
* In the Write operation the "bytes written" is really only used as an informant to
* the application. The Read operation is a bit different. For example, some types of buffering
* it may not matter if you set the number of bytes read. For example "Neither" you write
* directly into the user mode buffer so the user mode gets the data even if you don't
* tell it the amount. However if you remember how buffered I/O works? It makes a copy
* in memory. If the I/O manager doesn't know the size then it can't copy it back to the
* user mode buffer.
*
*
* IO_NO_INCREMENT - What is this? If an IRP request is taking a long time you may want to help
* the scheduler to re-schedule the thread as soon as possible. For example perhaps it issued
* a network request and went to sleep. Then on another thread the network request completes
* You may want to use one of the pre-defined constants or your own to increment the priority of
* that thread to be rescheduled being since it hasn't been scheduled in a while.
*
*/
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = dwDataRead;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_ReadNeither Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_UnSupportedFunction
*
* This is called when a major function is issued that isn't supported.
*
**********************************************************************/
NTSTATUS Example_UnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_NOT_SUPPORTED;
DbgPrint("Example_UnSupportedFunction Called \r\n");
/*
* This does not always need to be completed in this manner. The I/O Manager is friendly
* and in the simple case (as this driv
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -