153 lines
3.6 KiB
C
153 lines
3.6 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
io.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Author:
|
|
|
|
Thomas J. Dimitri (TommyD) 08-May-1992
|
|
|
|
Environment:
|
|
|
|
Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
#include "asyncall.h"
|
|
|
|
// asyncmac.c will define the global parameters.
|
|
#include "globals.h"
|
|
|
|
|
|
NTSTATUS
|
|
AsyncSetupIrp(
|
|
IN PASYNC_FRAME Frame,
|
|
IN PIRP irp
|
|
)
|
|
|
|
/*++
|
|
|
|
This is the routine which intializes the Irp
|
|
|
|
--*/
|
|
{
|
|
// PMDL mdl;
|
|
PDEVICE_OBJECT deviceObject=Frame->Info->DeviceObject;
|
|
PFILE_OBJECT fileObject=Frame->Info->FileObject;
|
|
|
|
irp->Tail.Overlay.OriginalFileObject = fileObject;
|
|
irp->RequestorMode = KernelMode;
|
|
irp->PendingReturned = FALSE;
|
|
|
|
//
|
|
// Fill in the service independent parameters in the IRP.
|
|
//
|
|
|
|
irp->UserEvent = NULL;
|
|
irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
|
|
irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
|
|
|
|
//
|
|
// Now determine whether this device expects to have data buffered to it
|
|
// or whether it performs direct I/O. This is based on the DO_BUFFERED_IO
|
|
// flag in the device object. If the flag is set, then a system buffer is
|
|
// allocated and the caller's data is copied into it. Otherwise, a Memory
|
|
// Descriptor List (MDL) is allocated and the caller's buffer is locked
|
|
// down using it.
|
|
//
|
|
|
|
if (deviceObject->Flags & DO_BUFFERED_IO) {
|
|
|
|
//
|
|
// The device does not support direct I/O. Allocate a system buffer,
|
|
// and copy the caller's data into it. This is done using an
|
|
// exception handler that will perform cleanup if the operation
|
|
// fails. Note that this is only done if the operation has a non-zero
|
|
// length.
|
|
//
|
|
|
|
irp->AssociatedIrp.SystemBuffer = Frame->Frame;
|
|
|
|
//
|
|
// Set the IRP_BUFFERED_IO flag in the IRP so that I/O completion
|
|
// will know that this is not a direct I/O operation.
|
|
//
|
|
|
|
irp->Flags = IRP_BUFFERED_IO;
|
|
|
|
|
|
} else if (deviceObject->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.
|
|
//
|
|
|
|
#if DBG
|
|
DbgPrintf(("The DeviceObject is NOT BUFFERED_IO!! IRP FAILURE!!\n"));
|
|
|
|
DbgBreakPoint();
|
|
#endif
|
|
|
|
} else {
|
|
|
|
//
|
|
// Pass the address of the caller's buffer to the device driver. It
|
|
// is now up to the driver to do everything.
|
|
//
|
|
|
|
irp->UserBuffer = Frame->Frame;
|
|
|
|
}
|
|
|
|
// For now, if we get this far, it means success!
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
PASYNC_IO_CTX
|
|
AsyncAllocateIoCtx(
|
|
BOOLEAN AllocateSync,
|
|
PVOID Context
|
|
)
|
|
{
|
|
PASYNC_IO_CTX AsyncIoCtx;
|
|
|
|
AsyncIoCtx = ExAllocateFromNPagedLookasideList(&AsyncIoCtxList);
|
|
|
|
if (AsyncIoCtx == NULL) {
|
|
return (NULL);
|
|
}
|
|
|
|
RtlZeroMemory(AsyncIoCtx, sizeof(ASYNC_IO_CTX));
|
|
AsyncIoCtx->Context = Context;
|
|
AsyncIoCtx->Sync = AllocateSync;
|
|
if (AllocateSync) {
|
|
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
|
KeInitializeEvent(&AsyncIoCtx->Event,
|
|
SynchronizationEvent,
|
|
(BOOLEAN)FALSE);
|
|
}
|
|
|
|
return (AsyncIoCtx);
|
|
}
|
|
|
|
VOID
|
|
AsyncFreeIoCtx(
|
|
PASYNC_IO_CTX AsyncIoCtx
|
|
)
|
|
{
|
|
ExFreeToNPagedLookasideList(&AsyncIoCtxList,
|
|
AsyncIoCtx);
|
|
}
|