📄 driverentry.cpp
字号:
/*
DriverEntry.cpp
Sheldon Instruments, Inc.
Abstract:
Update of the SI-DDK using WDM.
Revision History:
01Dec1998 - created by Robert Updike
15Mar2000 - added ForwardAndWait function Robert Updike
16Mar2000 - added support functions for the device queue Robert Updike
20Mar2000 - added IRP_MJ_CLEANUP to DriverEntry Robert Updike
*/
#include "driver.h"
#define NUM_OF_MAP_REGS 16000
NTSTATUS Sheldon_PnPAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);
VOID Sheldon_Unload(IN PDRIVER_OBJECT fdo);
/*
Function name:
DriverEntry
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path
to driver-specific key in the registry
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
*/
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, \
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
KdPrint(("SIWDM - Entering DriverEntry(), RegistryPath =\n %ws\n", RegistryPath->Buffer));
// Create dispatch points for create, close, unload
DriverObject->MajorFunction[IRP_MJ_CREATE] = Sheldon_Create;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Sheldon_Cleanup;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Sheldon_Close;
DriverObject->DriverUnload = Sheldon_Unload;
// User mode DeviceIoControl() calls will be routed here
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Sheldon_ProcessIOCTL;
// User mode ReadFile()/WriteFile() calls will be routed here
DriverObject->MajorFunction[IRP_MJ_WRITE] = Sheldon_Write;
DriverObject->MajorFunction[IRP_MJ_READ] = Sheldon_Read;
// routines for handling system PNP and power management requests
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Sheldon_ProcessSysControlIrp;
DriverObject->MajorFunction[IRP_MJ_PNP] = Sheldon_ProcessPnPIrp;
DriverObject->MajorFunction[IRP_MJ_POWER] = Sheldon_ProcessPowerIrp;
// The Functional Device Object (FDO) will not be created for PNP devices until
// this routine is called upon device plug-in.
DriverObject->DriverExtension->AddDevice = Sheldon_PnPAddDevice;
// The mechanism for handling read and write requests for a device that uses
// interrupts includes a Start I/O routine, an interrupt service routine, and
// a deferred procedure call routine that finishes handling interrupts. These are
// declared in ReadWrite.cpp and accessed through the Device Io Control calls.
KdPrint(("SIWDM - Exiting DriverEntry (%x)\n", ntStatus));
return ntStatus;
}
/*
Function name:
Sheldon_PnPAddDevice
Routine Description:
Creates a new functional device object.
Arguments:
DriverObject - pointer to the driver object
pdo - pointer to the physical device object
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
*/
NTSTATUS Sheldon_PnPAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{
KdPrint(("SIWDM - Entering Sheldon_PnPAddDevice\n"));
NTSTATUS ntStatus;
PDEVICE_OBJECT fdo;
PDEVICE_DESCRIPTION DeviceDescription;
UNICODE_STRING devname;
UNICODE_STRING linkname;
WCHAR namebuf[32];
WCHAR linkbuf[32];
static LONG devcount = -1;
_snwprintf(namebuf, arraysize(namebuf), L"\\Device\\SIWDM%d", InterlockedIncrement(&devcount));
RtlInitUnicodeString(&devname, namebuf);
_snwprintf(linkbuf, arraysize(linkbuf), L"\\DosDevices\\SIWDM%d", devcount);
RtlInitUnicodeString(&linkname, linkbuf);
ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devname, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
if(!NT_SUCCESS(ntStatus))
{
KdPrint(("SIWDM - Shelon_PnPAddDevice: IoCreateDevice failed (%x)\n", ntStatus));
return ntStatus;
}
ntStatus = IoCreateUnprotectedSymbolicLink(&linkname, &devname);
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
InitializeQueue(&pdx->dqReadWrite, Sheldon_StartIo);
__try
{
pdx->DeviceObject = fdo;
pdx->usage = 1;
KeInitializeEvent(&pdx->evRemove, NotificationEvent, FALSE);
pdx->removing = FALSE;
pdx->Timeout_ms = INITIAL_TIMEOUT;
pdx->state = STOPPED;
// Now register the PCI DMA controller
// First create a Device Description for the Busmastering capability
DeviceDescription = (PDEVICE_DESCRIPTION)ExAllocatePool(PagedPool, sizeof(DEVICE_DESCRIPTION));
RtlZeroMemory(DeviceDescription, sizeof(DEVICE_DESCRIPTION));
DeviceDescription->Version = DEVICE_DESCRIPTION_VERSION;
DeviceDescription->Master = TRUE;
DeviceDescription->ScatterGather = TRUE;
DeviceDescription->Dma32BitAddresses = TRUE;
DeviceDescription->IgnoreCount = FALSE;
DeviceDescription->InterfaceType = PCIBus;
DeviceDescription->DmaWidth = Width32Bits;
DeviceDescription->MaximumLength = AMCC_MAX_TRANSFER_SIZE;
// Now pass this description for both the read and the write adapters
pdx->ReadTransfer.NumberOfMapRegisters = NUM_OF_MAP_REGS;
pdx->ReadTransfer.Adapter = IoGetDmaAdapter(pdo, DeviceDescription, &pdx->ReadTransfer.NumberOfMapRegisters);
pdx->WriteTransfer.NumberOfMapRegisters = NUM_OF_MAP_REGS;
pdx->WriteTransfer.Adapter = IoGetDmaAdapter(pdo, DeviceDescription, &pdx->WriteTransfer.NumberOfMapRegisters);
// don't need this now, because we have the adapter objects
ExFreePool(DeviceDescription);
if(pdx->WriteTransfer.Adapter == NULL || pdx->ReadTransfer.Adapter == NULL)
{
KdPrint(("SIWDM - SheldonPnPAddDevice: Read or Write DMA Adapter returned a NULL\n"));
ntStatus = STATUS_ADAPTER_HARDWARE_ERROR;
__leave;
}
pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
if(!pdx->LowerDeviceObject)
{
KdPrint(("SIWDM - Sheldon_PnPAddDevice: IoAttachDeviceToDeviceStack failed\n"));
ntStatus = STATUS_DEVICE_REMOVED;
__leave;
}
KdPrint(("SIWDM - Sheldon_PnPAddDevice: Lower Device Object 0x%x\n", pdx->LowerDeviceObject));
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
}
__finally
{
if(!NT_SUCCESS(ntStatus))
{
if(pdx->LowerDeviceObject)
IoDetachDevice(pdx->LowerDeviceObject);
IoDeleteDevice(fdo);
}
}
KdPrint(("SIWDM - Exiting Sheldon_PnPAddDevice (%x)\n", ntStatus));
return ntStatus;
}
/*
Function name:
Sheldon_Unload
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object
Return Value:
*/
VOID Sheldon_Unload(IN PDRIVER_OBJECT DriverObject)
{
KdPrint(("SIWDM - Entering DriverUnload: DriverObject %8.8lX\n", DriverObject));
// Any global resources allocated in DriverEntry should be released here.
KdPrint(("SIWDM - Exiting DriverUnload\n"));
}
/*
Function name:
CompleteRequest
Routine Description:
Mark I/O request complete.
Arguments:
Irp - I/O request being serviced
ntStatus - NTSTATUS of the IRP
info - number of bytes to be returned
Return Value:
NT status code
*/
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS ntStatus, IN ULONG info)
{
KdPrint(("SIWDM - Entering CompleteRequest\n"));
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint(("SIWDM - Exiting CompleteRequest\n"));
return ntStatus;
}
/*
Function name:
LockDevice
Routine Description:
Locks the device object.
Arguments:
fdo - pointer to a functional device object to be locked
Return Value:
TRUE - if the device object was successfully locked,
FALSE - the device object is being deleted
*/
BOOLEAN LockDevice(IN PDEVICE_OBJECT fdo)
{
KdPrint(("SIWDM - LockDevice wrapper\n"));
return LockDevice((PDEVICE_EXTENSION) fdo->DeviceExtension);
}
/*
Function name:
LockDevice
Routine Description:
Locks the device object. The usage variable in the device extension should be greater
than one or the removing flag in the device extension should be set before calling this
function.
Arguments:
pdx - pointer to the device extension of the functional device object to be locked
Return Value:
TRUE - if the device object was successfully locked,
FALSE - the device object is being deleted
*/
BOOLEAN LockDevice(PDEVICE_EXTENSION pdx)
{
KdPrint(("SIWDM - Entering LockDevice\n"));
LONG usage = InterlockedIncrement(&pdx->usage);
// removing device
if(pdx->removing)
{
if(InterlockedDecrement(&pdx->usage) == 0)
KeSetEvent(&pdx->evRemove, 0, FALSE);
return FALSE;
}
KdPrint(("SIWDM - Exiting LockDevice\n"));
return TRUE;
}
/*
Function name:
UnlockDevice
Routine Description:
Unlocks the device object.
Arguments:
fdo - pointer to a functional device object to be unlocked
Return Value:
*/
VOID UnlockDevice(PDEVICE_OBJECT fdo)
{
KdPrint(("SIWDM - UnlockDevice wrapper\n"));
UnlockDevice((PDEVICE_EXTENSION) fdo->DeviceExtension);
}
/*
Function name:
UnlockDevice
Routine Description:
Unlocks the device object. The usage variable in the device extension should be greater
than or equal to one or the removing flag in the device extension should be set if usage
equals one before calling this function.
Arguments:
pdx - pointer to the device extension of the functional device object to be unlocked
Return Value:
*/
VOID UnlockDevice(PDEVICE_EXTENSION pdx)
{
LONG usage = InterlockedDecrement(&pdx->usage);
KdPrint(("SIWDM - Entering UnlockDevice\n"));
// removing device
if(usage == 0)
KeSetEvent(&pdx->evRemove, 0, FALSE);
KdPrint(("SIWDM - Exiting UnlockDevice\n"));
}
/*
Function name:
UnlockDeviceAndWait
Routine Description:
Unlocks the device object and waits for the event to complete.
Arguments:
pdx - pointer to the device extension of the functional device object to be unlocked
Return Value:
*/
VOID UnlockDeviceAndWait(PDEVICE_EXTENSION pdx)
{
KdPrint(("SIWDM - Entering UnlockDeviceAndWait\n"));
pdx->removing = TRUE;
UnlockDevice(pdx);
UnlockDevice(pdx);
KeWaitForSingleObject(&pdx->evRemove, Executive, KernelMode, FALSE, NULL);
KdPrint(("SIWDM - Exiting UnlockDeviceAndWait\n"));
}
/*
Function name:
OnRequestComplete
Routine Description:
This is the completion routine forwarded to other drivers.
Arguments:
fdo - pointer to a functional device object
Irp - pointer to the IO request packet
Event - pointer to the event
Return Value:
STATUS_MORE_PROCESSING_REQUIRED
*/
NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT Event)
{
// This would be necessary if the driver was not freeing the IRP itself.
//if(Irp->PendingReturned)
// IoMarkIrpPending(Irp);
KeSetEvent(Event, 1, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
/*
Function name:
ForwardAndWait
Routine Description:
Forwards the request to lower level drivers and waits for completion.
Arguments:
pdx - pointer to the device extension
Irp - pointer to the IO request packet
Return Value:
NTSTATUS code of Irp returned by other drivers.
*/
NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)
{
KEVENT event;
KdPrint(("SIWDM - Entering ForwardAndWait\n"));
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
(PVOID) &event, TRUE, TRUE, TRUE);
IoCallDriver(pdx->LowerDeviceObject, Irp);
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
KdPrint(("SIWDM - Exiting ForwardAndWait\n"));
return Irp->IoStatus.Status;
}
/*
Function name:
AbortRequests
Routine Description:
Begin rejecting new requests to the queue.
Arguments:
pdq - Address of queue object
ntStatus - Status to which fail new requests
Return Value:
*/
VOID AbortRequests(PDEVQUEUE pdq, NTSTATUS ntStatus)
{
KdPrint(("SIWDM - AbortRequests\n"));
pdq->abortstatus = ntStatus;
CleanupRequests(pdq, NULL, ntStatus);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -