📄 functions.c
字号:
* 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 = dwDataWritten;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_IoControl Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_WriteDirectIO
*
* This is called when a write is issued on the device handle (WriteFile/WriteFileEx)
*
* This version uses Direct I/O
*
**********************************************************************/
NTSTATUS Example_WriteDirectIO(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
UINT dwDataWritten = 0;
PCHAR pWriteDataBuffer;
DbgPrint("Example_WriteDirectIO 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)
{
pWriteDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
if(pWriteDataBuffer)
{
if(Example_WriteData((PEXAMPLE_LIST)pIoStackIrp->FileObject->FsContext, pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length, &dwDataWritten))
{
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 = dwDataWritten;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_WriteDirectIO Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_WriteBufferedIO
*
* This is called when a write is issued on the device handle (WriteFile/WriteFileEx)
*
* This version uses Buffered I/O
*
**********************************************************************/
NTSTATUS Example_WriteBufferedIO(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
UINT dwDataWritten = 0;
PCHAR pWriteDataBuffer;
DbgPrint("Example_WriteBufferedIO 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)
{
pWriteDataBuffer = (PCHAR)Irp->AssociatedIrp.SystemBuffer;
if(pWriteDataBuffer)
{
if(Example_WriteData((PEXAMPLE_LIST)pIoStackIrp->FileObject->FsContext, pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length, &dwDataWritten))
{
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 = dwDataWritten;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Example_WriteBufferedIO Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* Example_WriteNeither
*
* This is called when a write is issued on the device handle (WriteFile/WriteFileEx)
*
* This version uses Neither buffered or direct I/O. User mode memory is
* read directly.
*
**********************************************************************/
NTSTATUS Example_WriteNeither(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PCHAR pWriteDataBuffer;
UINT dwDataWritten = 0;
DbgPrint("Example_WriteNeither 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(Irp->UserBuffer)
{
ProbeForRead(Irp->UserBuffer, pIoStackIrp->Parameters.Write.Length, TYPE_ALIGNMENT(char));
pWriteDataBuffer = Irp->UserBuffer;
if(Example_WriteData((PEXAMPLE_LIST)pIoStackIrp->FileObject->FsContext, pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length, &dwDataWritten))
{
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -