📄 main.c
字号:
/*++
Copyright (c) 1990-2000 Changzhi Zhou All Rights Reserved
Module Name:
main.c
Abstract:
This module contains the entry points for a virtual serial driver
Author
Changzhi Zhou Jul 25, 2003
Environment:
Kernel mode
Revision History:
Changzhi Zhou Dec 5 2003
--*/
#include <ntddk.h>
#include <initguid.h>
#include <stdio.h>
#include "main.h"
#include "..\inc\wdmioctl.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, AddDevice)
#pragma alloc_text (PAGE, DispatchPower)
#pragma alloc_text (PAGE, Unload)
#endif
DEVICE_ARRAY gDeviceArray[ MAX_NUM_DEV ];
KSPIN_LOCK gSpinLock;
PACKET gPacketPool[ MAX_PACKET_NUM ];
LIST_ENTRY gIdleQueue;
KSPIN_LOCK gPoolSpinLock;
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
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.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
//ULONG ulIndex;
ULONG i;
PDRIVER_DISPATCH * dispatch;
UNREFERENCED_PARAMETER (RegistryPath);
DebugPrint (("----------- Virtual Serial Device Build on %s %s ----------\n", __DATE__, __TIME__ ));
//
// Create dispatch points
//
/*
for (ulIndex = 0, dispatch = DriverObject->MajorFunction;
ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
ulIndex++, dispatch++) {
*dispatch = DefaultPnpHandler;
}
*/
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_CREATE] = RequestCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = RequestClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP ] = RequestCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RequestControl;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->DriverUnload = Unload;
// Initialize global varible
RtlZeroMemory( gDeviceArray, sizeof( DEVICE_ARRAY ) * MAX_NUM_DEV );
KeInitializeSpinLock( &gSpinLock );
RtlZeroMemory( gPacketPool, sizeof( PACKET ) * MAX_PACKET_NUM );
InitializeListHead( &gIdleQueue );
KeInitializeSpinLock( &gPoolSpinLock );
for( i = 0; i < MAX_PACKET_NUM; i++)
{
InsertTailList( &gIdleQueue, &(gPacketPool[ i ].ListEntry) );
}
return status;
}
NTSTATUS
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
The Plug & Play subsystem is handing us a brand new PDO, for which we
(by means of INF registration) have been asked to provide a driver.
We need to determine if we need to be in the driver stack for the device.
Create a function device object to attach to the stack
Initialize that device object
Return status success.
Remember: We can NOT actually send ANY non pnp IRPS to the given driver
stack, UNTIL we have received an IRP_MN_START_DEVICE.
Arguments:
DeviceObject - pointer to a device object.
PhysicalDeviceObject - pointer to a device object created by the
underlying bus driver.
Return Value:
NT status code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension;
PAGED_CODE ();
//
// Create a device object.
//
status = SerialCreateDevObj(DriverObject, &deviceObject);
if (!NT_SUCCESS (status)) {
//
// Returning failure here prevents the entire stack from functioning,
// but most likely the rest of the stack will not be able to create
// device objects either, so it is still OK.
//
DebugPrint(("SerialCreateDevice failed with status %d\n", status ));
return status;
}
DebugPrint (("AddDevice PDO (0x%x) FDO (0x%x)\n", PhysicalDeviceObject, deviceObject));
deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
deviceExtension->NextLowerDriver = IoAttachDeviceToDeviceStack (
deviceObject,
PhysicalDeviceObject);
//
// Failure for attachment is an indication of a broken plug & play system.
//
if(NULL == deviceExtension->NextLowerDriver) {
IoDeleteDevice(deviceObject);
return STATUS_UNSUCCESSFUL;
}
INITIALIZE_PNP_STATE(deviceExtension);
DebugPrint(("AddDevice: %x to %x->%x \n", deviceObject,
deviceExtension->NextLowerDriver,
PhysicalDeviceObject));
if( !NT_SUCCESS ( status ) ){
DebugPrint(( "AddDevice: IoRegisterDeviceInterface failed (%x) \n", status ));
IoDetachDevice( deviceExtension->NextLowerDriver );
gDeviceArray[ deviceExtension->localInstance ].deviceExtension = NULL;
IoDeleteDevice( deviceObject );
return status;
}
deviceObject->Flags |= ( DO_BUFFERED_IO | DO_POWER_PAGABLE );
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
#if 0
FilterCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
A completion routine for use when calling the lower device objects to
which our filter deviceobject is attached.
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to a PnP Irp.
Context - Pointer to an event object
Return Value:
NT Status is returned.
--*/
{
UNREFERENCED_PARAMETER(DeviceObject);
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// We could switch on the major and minor functions of the IRP to perform
// different functions, but we know that Context is an event that needs
// to be set.
//
KeSetEvent((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
//
// Allows the caller to use the IRP after it is completed
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
#endif
NTSTATUS
DispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch routine for power irps.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
NT Status code
--*/
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PAGED_CODE ();
DebugPrint(("Enter DispatchPower routine...\n"));
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
DebugPrint(("NextLowerDriver: 0x%x\n", deviceExtension->NextLowerDriver ));
status = PoCallDriver(deviceExtension->NextLowerDriver, Irp);
DebugPrint(("-Exit Power\n") );
return status;
}
VOID
Unload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources in DriverEntry, etc.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID.
--*/
{
PAGED_CODE ();
//
// The device object(s) should be NULL now
// (since we unload, all the devices objects associated with this
// driver must be deleted.
//
DebugPrint( ("Is unloading......\n") );
ASSERT(DriverObject->DeviceObject == NULL);
//
// We should not be unloaded until all the devices we control
// have been removed from our queue.
//
DebugPrint (("Unload: unload\n"));
return;
}
NTSTATUS RequestCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
/*++
Routine Description:
Create the device
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to an IRP_MJ_CREATE
Return Value:
NT Status is return.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -