Look at this example code we using in our driver.
NTSTATUS OwnRead(
IN PDEVICE_OBJECT NextDeviceObject,
IN PFILE_OBJECT FileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset,
IN KPROCESSOR_MODE requestorMode
)
//////////////////////////////////////////////////////////////////////////
// sends IRP_MJ_READ for read data from file
// in this function not implemented using of Fast IO routines
//////////////////////////////////////////////////////////////////////////
{
NTSTATUS status;
LARGE_INTEGER fileOffset = {0,0};
KEVENT event;
PIRP irp = NULL;
PIO_STACK_LOCATION irpSp = NULL;
PFAST_IO_DISPATCH fastIoDispatch = NULL;
ULONG keyValue = 0;
if (!NextDeviceObject || !FileObject || !IoStatusBlock || !Buffer){
return STATUS_INVALID_PARAMETER;
}
//
// capture ByteOffset parameter if it is present.
//
if (ARGUMENT_PRESENT( ByteOffset )) {
fileOffset = *ByteOffset;
}
if (requestorMode != KernelMode)
{
//Validate offset
if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING)
{
//
// The file was opened without intermediate
buffering enabled.
// Check that the Buffer is properly aligned, and
that the
// length is an integral number of the block size.
//
if ((NextDeviceObject->SectorSize &&
(Length & (NextDeviceObject->SectorSize -
1))) ||
(ULONG_PTR) Buffer &
NextDeviceObject->AlignmentRequirement)
{
//
// Check for sector sizes that are not a
power of two.
//
if ((NextDeviceObject->SectorSize &&
Length %
NextDeviceObject->SectorSize) ||
(ULONG_PTR) Buffer &
NextDeviceObject->AlignmentRequirement)
{
ASSERT( FALSE );
return STATUS_INVALID_PARAMETER;
}
}
//
// If a ByteOffset parameter was specified, ensure
that it
// is a valid argument.
//
if (ARGUMENT_PRESENT( ByteOffset ))
{
if (NextDeviceObject->SectorSize &&
(fileOffset.LowPart &
(NextDeviceObject->SectorSize - 1)))
{
ASSERT( FALSE );
return STATUS_INVALID_PARAMETER;
}
}
}
}
//
// Get the address of the driver object’s Fast I/O dispatch
structure.
//
fastIoDispatch = NextDeviceObject->DriverObject->FastIoDispatch;
//
// Make a special check here to determine whether this is a
synchronous
// I/O operation. If it is, then wait here until the file is owned
by
// the current thread.
//
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
if (/*!ARGUMENT_PRESENT( ByteOffset ) || */ /*!!!*/
(fileOffset.LowPart ==
FILE_USE_FILE_POINTER_POSITION &&
fileOffset.HighPart == -1))
{
fileOffset = FileObject->CurrentByteOffset;
}
//
// Turbo read support. If the file is currently cached on
this
// file object, then call the Cache Manager directly via
FastIoRead
// and try to successfully complete the request here. Note
if
// FastIoRead returns FALSE or we get an I/O error, we
simply
// fall through and go the “long way” and create an Irp.
//
if (FileObject->PrivateCacheMap)
{
IO_STATUS_BLOCK localIoStatus;
ASSERT(fastIoDispatch &&
fastIoDispatch->FastIoRead);
//
// Negative file offsets are illegal.
//
if (fileOffset.HighPart < 0) {
return STATUS_INVALID_PARAMETER;
}
if (fastIoDispatch->FastIoRead( FileObject,
&fileOffset,
Length,
TRUE,
keyValue,
Buffer,
&localIoStatus,
NextDeviceObject )
&&
((localIoStatus.Status == STATUS_SUCCESS) ||
(localIoStatus.Status ==
STATUS_BUFFER_OVERFLOW) ||
(localIoStatus.Status ==
STATUS_END_OF_FILE)))
{
__try {
*IoStatusBlock = localIoStatus;
}__except( EXCEPTION_EXECUTE_HANDLER ) {
localIoStatus.Status =
GetExceptionCode();
localIoStatus.Information = 0;
}
return localIoStatus.Status;
}
}
}
//
// Negative file offsets are illegal.
//
if (fileOffset.HighPart < 0) {
return STATUS_INVALID_PARAMETER;
}
// Set the file object to the Not-Signaled state
KeInitializeEvent( &event, NotificationEvent, FALSE );
//
IoStatusBlock->Status = STATUS_SUCCESS;
IoStatusBlock->Information = 0;
// Allocate and initialize the I/O Request Packet (IRP) for this
operation.
irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
if (irp == NULL) {
// An IRP could not be allocated. Cleanup and return an
appropriate error status code
return STATUS_INSUFFICIENT_RESOURCES;
}
irp->Tail.Overlay.OriginalFileObject = FileObject;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL;
irp->RequestorMode = KernelMode;
irp->PendingReturned = FALSE;
irp->Cancel = FALSE;
irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
// Fill in the service independent parameters in the IRP.
irp->MdlAddress = NULL;
irp->UserIosb = IoStatusBlock;
irp->UserEvent = NULL;
irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
//
// Get a pointer to the stack location for the first driver. This
will be
// used to pass the original function codes and parameters. Note
that
// setting the major function here also sets:
//
// MinorFunction = 0;
// Flags = 0;
// Control = 0;
//
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_READ;
irpSp->MinorFunction = IRP_MN_NORMAL;
irpSp->FileObject = FileObject;
//
// Now determine whether this device expects to have data buffered
to it
// or whether it performs direct I/O.
irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
if (NextDeviceObject->Flags & DO_BUFFERED_IO) {
if (Length) {
irp->AssociatedIrp.SystemBuffer = Buffer;
}
}else if (NextDeviceObject->Flags & DO_DIRECT_IO) {
//
// This is a direct I/O operation. Allocate an MDL and
invoke the
// memory management routine to lock the buffer into memory.
This
// is done using an exception handler that will perform
cleanup if
// the operation fails. Note that no MDL is allocated, nor
is any
// memory probed or locked if the length of the request was
zero.
//
irp->Flags = 0;
irp->MdlAddress;
if (Length) {
__try {
//
// Allocate an MDL, charging quota for it,
and hang it off of
// the IRP. Probe and lock the pages
associated with the
// caller’s buffer for write access and fill
in the MDL with
// the PFNs of those pages.
//
irp->MdlAddress = IoAllocateMdl( Buffer,
Length, FALSE, TRUE, irp );
if (irp->MdlAddress == NULL) {
IoFreeIrp(irp);
return STATUS_INSUFFICIENT_RESOURCES
;
}
MmProbeAndLockPages( irp->MdlAddress,
KernelMode, IoWriteAccess );
}__except(EXCEPTION_EXECUTE_HANDLER) {
IoFreeIrp(irp);
return GetExceptionCode();
}
}
}else {
// Pass the address of the user’s buffer so the driver has
access to
// it. It is now the driver’s responsibility to do
everything.
irp->Flags = 0;
irp->UserBuffer = Buffer;
}
// If this read operation is supposed to be performed with caching
disabled
// set the disable flag in the IRP so no caching is performed.
if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
irp->Flags |= IRP_NOCACHE | IRP_READ_OPERATION |
IRP_DEFER_IO_COMPLETION;
} else {
irp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION;
}
// Copy the caller’s parameters to the service-specific portion of
the
// IRP.
irpSp->Parameters.Read.Length = Length;
irpSp->Parameters.Read.Key = 0;
irpSp->Parameters.Read.ByteOffset = fileOffset;
IoSetCompletionRoutine( irp,
OwnReadWriteCompletion,
&event,
TRUE,
TRUE,
TRUE );
status = IoCallDriver( NextDeviceObject, irp );
if (STATUS_PENDING == status) {
KeWaitForSingleObject( &event,
Executive,
KernelMode,
FALSE,
NULL );
}
return IoStatusBlock->Status;
}
Andrey Gunko
soft Xpansion GmbH & Co.KG
Programmer
Powered by eKnow-how
Konigsallee 45 D-44789 Bochum Tel: +49 234 2984171 Fax: +49 234
2984172 Internet: [www.maus-soft.com]
|-----Original Message-----
|From: xxxxx@lists.osr.com [mailto:bounce-263408-
|xxxxx@lists.osr.com] On Behalf Of Roman Kudinov
|Sent: Thursday, September 21, 2006 3:16 PM
|To: Windows File Systems Devs Interest List
|Subject: Re:[ntfsd] Why my IRP_MJ_READ fails
|
|We use IoBuildAsycnronoususFsdRequest for building IRP.
|
|The problem was that it is necessary to initialize MDL field of IRP
|properly.
|
|But now I get another problem - after I call IoCallDriver with my IRP I get
|the infinite recursion. I.e. I get another IRP_MJ_READ which seems to be
|initated by the underlying driver in response to my IRP…
|
|I am completely in stuck.
|
|
|Thank you,
|Roman
|
|
|“Maxim S. Shatskih” ???/??? ? ???
|???: news:xxxxx@ntfsd…
|> >My IRP_MJ_READ fails if I roll it down from the paging i/o, though it
|works
|> fine
|> >from non paged i/o. What can be the reason?
|>
|> Paging IO paths are executing on APC_LEVEL, where you cannot use
|ZwXxxFile
|and
|> IoBuildSynchronousFsdRequest or IoBuildDeviceIoControlRequest.
|>
|> Use IoAllocateIrp or IoBuildAsynchronousFsdRequest instead.
|>
|> Maxim Shatskih, Windows DDK MVP
|> StorageCraft Corporation
|> xxxxx@storagecraft.com
|> http://www.storagecraft.com
|>
|>
|
|
|
|—
|Questions? First check the IFS FAQ at
|https://www.osronline.com/article.cfm?id=17
|
|You are currently subscribed to ntfsd as: xxxxx@maus.donetsk.ua
|To unsubscribe send a blank email to xxxxx@lists.osr.com