📄 pcmciadevice.cpp
字号:
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS PcmciaDevice::Create(KIrp I)
{
NTSTATUS status;
t << "Entering PcmciaDevice::Create, " << I << EOL;
// TODO: Add driver specific create handling code here
// Generally a create IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO. We have found for some devices, the
// PDO is not expecting this Irp and returns an error code.
// The default wizard code, therefore completes the Irp here using
// PnpComplete(). The following commented code could be used instead
// of PnpComplete() to pass the Irp to the PDO, which would complete it.
//
// I.ForceReuseOfCurrentStackLocationInCalldown();
// status = m_Lower.PnpCall(this, I);
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "PcmciaDevice::Create Status " << (ULONG)status << EOL;
return status;
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::Close
//
// Routine Description:
// Handler for IRP_MJ_CLOSE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS PcmciaDevice::Close(KIrp I)
{
NTSTATUS status;
t << "Entering PcmciaDevice::Close, " << I << EOL;
// TODO: Add driver specific close handling code here
// Generally a close IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO. We have found for some devices, the
// PDO is not expecting this Irp and returns an error code.
// The default wizard code, therefore completes the Irp here using
// PnpComplete(). The following commented code could be used instead
// of PnpComplete() to pass the Irp to the PDO, which would complete it.
//
// I.ForceReuseOfCurrentStackLocationInCalldown();
// status = m_Lower.PnpCall(this, I);
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "PcmciaDevice::Close Status " << (ULONG)status << EOL;
return status;
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::Cleanup
//
// Routine Description:
// Handler for IRP_MJ_CLEANUP
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS PcmciaDevice::CleanUp(KIrp I)
{
t << "Entering CleanUp, " << I << EOL;
// TODO: Insert your code to respond to the CLEANUP message.
// This code cleans up the single Wizard created queue. If you
// have created additional queues, or have any outstanding Irps
// stored in some other fashion in your driver, you should clean
// these up as well for the file object specified in the cleanup Irp.
m_DriverManagedQueue.PnpCleanUp(this, I.FileObject());
return I.PnpComplete(this, STATUS_SUCCESS);
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::SerialRead
//
// Routine Description:
// Handler for serialized READ
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is called when the IRP is removed from the
// STARTIO queue. This guarantees that multiple requests are
// never processed simultaneously.
//
// This routine is called at dispatch level.
//
void PcmciaDevice::SerialRead(KIrp I)
{
t << "Entering PcmciaDevice::SerialRead, " << I << EOL;
NTSTATUS status = STATUS_SUCCESS;
// Declare a memory object
KMemory Mem(I.Mdl());
// Use the memory object to create a pointer to the caller's buffer
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG dwTotalSize = I.ReadSize(CURRENT); // Requested read size
ULONG dwBytesRead = 0; // Count of bytes read
// TODO: If the read can be satisfied immediately, set the Information
// and Status fields now, then call NextIrp to complete this IRP
// and start processing the next IRP in the queue.
// TODO: If the data is not yet available, initiate a request to the
// physical device here, and defer the Information, Status,
// and NextIrp handling until the hardware indicates that the
// read is complete. Typically, this might be handled in a
// DPC that is called after the hardware finishes transferring
// the data.
// TODO: To satisfy the read now, transfer data from the device to
// caller's buffer at "pBuffer". Then, indicate how much data was
// transferred:
I.Information() = dwBytesRead;
I.Status() = status;
// PnpNextIrp completes this IRP and starts processing
// for the next IRP in the driver managed queue.
// TODO: The Wizard creates a single queue for all Irps.
// If you have created additional queues, select
// the appropriate queue for this Irp here.
m_DriverManagedQueue.PnpNextIrp(I);
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::Read
//
// Routine Description:
// Handler for IRP_MJ_READ
//
// Parameters:
// I Current IRP
//
// Return Value:
// NTSTATUS Result code
//
// Comments:
// This routine handles read requests.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS PcmciaDevice::Read(KIrp I)
{
t << "Entering PcmciaDevice::Read, " << I << EOL;
// TODO: Check the incoming request. Replace "FALSE" in the following
// line with a check that returns TRUE if the request is not valid.
if (FALSE) // If (Request is invalid)
{
// Invalid parameter in the Read request
I.Information() = 0;
return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
}
// Always ok to read 0 elements.
if (I.ReadSize() == 0)
{
I.Information() = 0;
return I.PnpComplete(this, STATUS_SUCCESS);
}
// Queue the IRP for processing in the driver managed queue.
// The actual read function is performed in SerialRead
// TODO: The Wizard creates a single queue for all Irps.
// If you have created additional queues, select
// the appropriate queue for this Irp here.
return m_DriverManagedQueue.QueueIrp(I);
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::SerialWrite
//
// Routine Description:
// Handler for serialized WRITE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is called when the IRP is removed from the
// STARTIO queue. This guarantees that multiple requests are
// never processed simultaneously.
//
void PcmciaDevice::SerialWrite(KIrp I)
{
t << "Entering PcmciaDevice::SerialWrite, " << I << EOL;
NTSTATUS status = STATUS_SUCCESS;
// Declare a memory object
KMemory Mem(I.Mdl());
// Use the memory object to create a pointer to the caller's buffer
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG dwTotalSize = I.WriteSize(CURRENT);
ULONG dwBytesSent = 0;
// TODO: If the write can be satisfied immediately, set the Information
// and Status fields now, then call NextIrp to complete this IRP
// and start processing the next IRP in the queue.
// TODO: If the device cannot accept all of the data yet, initiate a
// request to the physical device here, and defer the Information,
// Status, and NextIrp handling until the hardware indicates that
// the write is complete. Typically, this might be handled in a
// DPC that is called after the hardware finishes transferring
// the data.
// TODO: To satisfy the write now, transfer data to the device
// from caller's buffer at "pBuffer". Then, indicate how much
// data was transferred:
I.Information() = dwBytesSent;
I.Status() = status;
// PnpNextIrp completes this IRP and starts processing
// for the next IRP in the driver managed queue.
// TODO: The Wizard creates a single queue for all Irps.
// If you have created additional queues, select
// the appropriate queue for this Irp here.
m_DriverManagedQueue.PnpNextIrp(I);
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::Write
//
// Routine Description:
// Handler for IRP_MJ_WRITE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
// This routine handles write requests.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS PcmciaDevice::Write(KIrp I)
{
t << "Entering PcmciaDevice::Write, " << I << EOL;
// TODO: Check the incoming request. Replace "FALSE" in the following
// line with a check that returns TRUE if the request is not valid.
if (FALSE)
{
// Invalid parameter in the Write request
I.Information() = 0;
return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
}
// Always ok to write 0 elements.
if (I.WriteSize() == 0)
{
I.Information() = 0;
return I.PnpComplete(this, STATUS_SUCCESS);
}
// Queue the IRP for processing in the driver managed queue.
// The actual write function is performed in SerialWrite
// TODO: The Wizard creates a single queue for all Irps.
// If you have created additional queues, select
// the appropriate queue for this Irp here.
return m_DriverManagedQueue.QueueIrp(I);
}
////////////////////////////////////////////////////////////////////////
// PcmciaDevice::DeviceControl
//
// Routine Description:
// Handler for IRP_MJ_DEVICE_CONTROL
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is the first handler for Device Control requests.
// Some function codes may be handled immediately,
// while others may be serialized through the StartIo routine.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS PcmciaDevice::DeviceControl(KIrp I)
{
NTSTATUS status;
t << "Entering PcmciaDevice::Device Control, " << I << EOL;
switch (I.IoctlCode())
{
default:
// Unrecognized IOCTL request
status = STATUS_INVALID_PARAMETER;
break;
}
// If the IRP was queued, or its IOCTL handler deferred processing using some
// driver specific scheme, the status variable is set to STATUS_PENDING.
// In this case we simply return that status, and the IRP will be completed
// later. Otherwise, complete the IRP using the status returned by the
// IOCTL handler.
if (status == STATUS_PENDING)
{
return status;
}
else
{
return I.PnpComplete(this, status);
}
}
////////////////////////////////////////////////////////////////////////////////
// PcmciaDevice_DriverManagedQueue::StartIo
//
// Routine Description:
// This routine is called when an IRP is taken off
// the Driver Managed Queue (used for serializing I/O) and
// presented for processing.
//
// Parameters:
// I - IRP removed from queue
//
// Return Value:
// None
//
// Comments:
//
VOID PcmciaDevice_DriverManagedQueue::StartIo(KIrp I)
{
t << "Entering PcmciaDevice_DriverManagedQueue StartIo, " << I;
// The KDriverManagedQueueEx class gives us the Irp in a non-cancelable state
// (cancel routine set to NULL) so we can process it without having to worry
// about clearing the cancel routine first, as is the case with system queuing,
// or the legacy class KDriverManagedQueue. You may want to set a different cancel
// routine here, or at other points during the processing of this Irp.
// Find the device class so we can call the serialized
// routines in the device class. The handlers can be
// moved to the DriverManagedQueue class if it is more
// convenient.
PcmciaDevice *pDev = (PcmciaDevice *) KDevicePTR(I.DeviceObject());
// Start processing request.
// Switch on the IRP's function:
switch (I.MajorFunction())
{
case IRP_MJ_READ:
pDev->SerialRead(I);
break;
case IRP_MJ_WRITE:
pDev->SerialWrite(I);
break;
case IRP_MJ_DEVICE_CONTROL:
switch (I.IoctlCode())
{
default:
// We queued a request that shouldn't have been queued
// (should never get here)
ASSERT(FALSE);
break;
}
break;
default:
// Error - unexpected IRP received
// NextIrp completes this IRP and starts processing
// for the next IRP in the queue.
ASSERT(FALSE);
I.Status() = STATUS_INVALID_PARAMETER;
PnpNextIrp(I);
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -