📄 firefly.c
字号:
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Module Name:
firefly.c
Abstract:
This module contains filter driver code for the firefly device.
Environment:
Kernel mode
Revision History:
Adrian J. Oney - Written March 17th, 2001
(based on Toaster DDK filter sample)
Eliyas Yakub - Cleaned up for DDK - 18-Oct-2002
--*/
#include "firefly.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, FireflyAddDevice)
#pragma alloc_text(PAGE, FireflyUnload)
#pragma alloc_text(PAGE, FireflyDispatchPnp)
#pragma alloc_text(PAGE, FireflyDispatchPower)
#pragma alloc_text(PAGE, FireflyDispatchWmi)
#pragma alloc_text(PAGE, FireflyRegisterWmi)
#pragma alloc_text(PAGE, FireflySetWmiDataItem)
#pragma alloc_text(PAGE, FireflySetWmiDataBlock)
#pragma alloc_text(PAGE, FireflyQueryWmiDataBlock)
#pragma alloc_text(PAGE, FireflyQueryWmiRegInfo)
#endif
UNICODE_STRING GlobalRegistryPath;
//
// Defines for the various WMI blocks we are exposing
//
#define WMI_FIREFLY_DRIVER_INFORMATION 0
//
// Guids for the various WMI blocks we are exposing
//
WMIGUIDREGINFO FireflyWmiGuidList[1] = {
{ &FIREFLY_WMI_STD_DATA_GUID, 1, 0 } // driver information
};
//
// Where they are described.
//
#define MOFRESOURCENAME L"FireflyWMI"
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:
NT status code
--*/
{
USHORT regPathLen;
ULONG ulIndex;
PDRIVER_DISPATCH * dispatch;
DebugPrint(("Entered the Driver Entry\n"));
//
// Cache away the registry path.
//
regPathLen = RegistryPath->Length;
GlobalRegistryPath.MaximumLength = regPathLen + sizeof(UNICODE_NULL);
GlobalRegistryPath.Length = regPathLen;
GlobalRegistryPath.Buffer = ExAllocatePoolWithTag(
PagedPool,
GlobalRegistryPath.MaximumLength,
POOL_TAG
);
if (GlobalRegistryPath.Buffer == NULL) {
DebugPrint(("Couldn't allocate pool for registry path!\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&GlobalRegistryPath, RegistryPath);
//
// Create dispatch points
//
for (ulIndex = 0, dispatch = DriverObject->MajorFunction;
ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
ulIndex++, dispatch++) {
*dispatch = FireflyForwardIrp;
}
DriverObject->MajorFunction[IRP_MJ_PNP] = FireflyDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = FireflyDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = FireflyDispatchWmi;
DriverObject->DriverExtension->AddDevice = FireflyAddDevice;
DriverObject->DriverUnload = FireflyUnload;
return STATUS_SUCCESS;
}
NTSTATUS
FireflyAddDevice(
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;
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION deviceExtension = NULL;
PAGED_CODE();
//
// Create a filter device object.
//
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
NULL, // No Name
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&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.
//
return status;
}
DebugPrint((
"AddDevice PDO (0x%x) FDO (0x%x)\n",
PhysicalDeviceObject,
deviceObject
));
//
// Get a pointer to our device extension.
//
deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
//
// Save some information for later.
//
deviceExtension->Self = deviceObject;
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;
}
deviceObject->Flags |= deviceExtension->NextLowerDriver->Flags &
(DO_BUFFERED_IO | DO_DIRECT_IO |
DO_POWER_PAGABLE | DO_POWER_INRUSH);
deviceObject->DeviceType = deviceExtension->NextLowerDriver->DeviceType;
deviceObject->Characteristics =
deviceExtension->NextLowerDriver->Characteristics;
//
// Set the initial state of the Filter DO
//
INITIALIZE_PNP_STATE(deviceExtension);
//
// Let us use remove lock to keep count of IRPs so that we don't
// deteach or delete our deviceobject until all pending I/Os in our
// devstack are completed. Remlock is required to protect us from
// various race conditions.
//
IoInitializeRemoveLock (&deviceExtension->RemoveLock ,
POOL_TAG,
1, // MaxLockedMinutes
5); // HighWatermark, this parameter is
// used only on checked build.
DebugPrint((
"AddDevice: %x to %x->%x \n",
deviceObject,
deviceExtension->NextLowerDriver,
PhysicalDeviceObject
));
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
VOID
FireflyUnload(
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();
//
// There should be no remaining device object(s) now.
//
ASSERT(DriverObject->DeviceObject == NULL);
//
// Free the registry path we cached away.
//
if (GlobalRegistryPath.Buffer) {
ExFreePool(GlobalRegistryPath.Buffer);
}
//
// We should not be unloaded until all the devices we control
// have been removed from our queue.
//
DebugPrint(("unload\n"));
return;
}
NTSTATUS
FireflyDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these the driver will completely ignore. In all cases it must pass
on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack, nextStack;
NTSTATUS status;
KEVENT event;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
DebugPrint((
"FilterDO %s IRP:0x%x \n",
PnPMinorFunctionString(irpStack->MinorFunction),
Irp
));
status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS (status)) {
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
switch(irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// The device is starting.
//
// We cannot touch the device (send it any non pnp irps) until a
// start device has been passed down to the lower drivers.
//
KeInitializeEvent(&event,
NotificationEvent,
FALSE
);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
FireflySynchronousCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);
if (STATUS_PENDING == status) {
KeWaitForSingleObject(
&event,
Executive, // Waiting for reason of a driver
KernelMode, // Waiting in kernel mode
FALSE, // No alert
NULL // No timeout
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -