277 lines
5.8 KiB
C
277 lines
5.8 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
initunlo.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code that is very specific to initialization
|
|
and unload operations in the irenum driver
|
|
|
|
Author:
|
|
|
|
Brian Lieuallen, 7-13-2000
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History :
|
|
|
|
--*/
|
|
|
|
#include "internal.h"
|
|
|
|
ULONG DebugFlags;
|
|
ULONG DebugMemoryTag='nErI';
|
|
PVOID PagedCodeSectionHandle;
|
|
UNICODE_STRING DriverEntryRegPath;
|
|
|
|
ULONG EnumStaticDevice=0;
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
VOID
|
|
IrEnumUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
NTSTATUS
|
|
UnHandledDispatch(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
);
|
|
|
|
|
|
|
|
#pragma alloc_text(INIT,DriverEntry)
|
|
#pragma alloc_text(PAGE,IrEnumUnload)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The entry point that the system point calls to initialize
|
|
any driver.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Just what it says, really of little use
|
|
to the driver itself, it is something that the IO system
|
|
cares more about.
|
|
|
|
PathToRegistry - points to the entry for this driver
|
|
in the current control set of the registry.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if we could initialize a single device,
|
|
otherwise STATUS_NO_SUCH_DEVICE.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// We use this to query into the registry as to whether we
|
|
// should break at driver entry.
|
|
//
|
|
RTL_QUERY_REGISTRY_TABLE paramTable[4];
|
|
ULONG zero = 0;
|
|
ULONG debugLevel = 0;
|
|
ULONG debugFlags = 0;
|
|
ULONG shouldBreak = 0;
|
|
|
|
|
|
DriverEntryRegPath.Length=RegistryPath->Length;
|
|
DriverEntryRegPath.MaximumLength=DriverEntryRegPath.Length+sizeof(WCHAR);
|
|
|
|
|
|
DriverEntryRegPath.Buffer=ALLOCATE_PAGED_POOL(DriverEntryRegPath.MaximumLength);
|
|
|
|
if (DriverEntryRegPath.Buffer == NULL) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
DriverEntryRegPath.Buffer,
|
|
RegistryPath->Buffer,
|
|
RegistryPath->Length
|
|
);
|
|
|
|
//
|
|
// NULL terminate the string
|
|
//
|
|
DriverEntryRegPath.Buffer[RegistryPath->Length/sizeof(WCHAR)]=L'\0';
|
|
|
|
//
|
|
// Since the registry path parameter is a "counted" UNICODE string, it
|
|
// might not be zero terminated. For a very short time allocate memory
|
|
// to hold the registry path zero terminated so that we can use it to
|
|
// delve into the registry.
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
¶mTable[0],
|
|
sizeof(paramTable)
|
|
);
|
|
|
|
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
|
paramTable[0].Name = L"BreakOnEntry";
|
|
paramTable[0].EntryContext = &shouldBreak;
|
|
paramTable[0].DefaultType = REG_DWORD;
|
|
paramTable[0].DefaultData = &zero;
|
|
paramTable[0].DefaultLength = sizeof(ULONG);
|
|
|
|
paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
|
paramTable[1].Name = L"DebugFlags";
|
|
paramTable[1].EntryContext = &debugFlags;
|
|
paramTable[1].DefaultType = REG_DWORD;
|
|
paramTable[1].DefaultData = &zero;
|
|
paramTable[1].DefaultLength = sizeof(ULONG);
|
|
|
|
paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
|
paramTable[2].Name = L"EnumStaticDevice";
|
|
paramTable[2].EntryContext = &EnumStaticDevice;
|
|
paramTable[2].DefaultType = REG_DWORD;
|
|
paramTable[2].DefaultData = &zero;
|
|
paramTable[2].DefaultLength = sizeof(ULONG);
|
|
|
|
|
|
if (!NT_SUCCESS(RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
|
|
DriverEntryRegPath.Buffer,
|
|
¶mTable[0],
|
|
NULL,
|
|
NULL
|
|
))) {
|
|
|
|
shouldBreak = 0;
|
|
|
|
}
|
|
|
|
|
|
#if DBG
|
|
DebugFlags=debugFlags;
|
|
#endif
|
|
|
|
if (shouldBreak) {
|
|
|
|
DbgBreakPoint();
|
|
|
|
}
|
|
//
|
|
// pnp driver entry point
|
|
//
|
|
DriverObject->DriverExtension->AddDevice = IrEnumAddDevice;
|
|
|
|
//
|
|
// Initialize the Driver Object with driver's entry points
|
|
//
|
|
DriverObject->DriverUnload = IrEnumUnload;
|
|
|
|
|
|
{
|
|
ULONG i;
|
|
|
|
for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|
|
|
DriverObject->MajorFunction[i]=UnHandledDispatch;
|
|
}
|
|
}
|
|
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = IrEnumPnP;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = IrEnumPower;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IrEnumWmi;
|
|
|
|
|
|
D_PNP(DbgPrint("IRENUM: DriverEntry\n");)
|
|
|
|
|
|
//
|
|
// lock and unlock here so we can get a handle to the section
|
|
// so future calls will be faster
|
|
//
|
|
PagedCodeSectionHandle=MmLockPagableCodeSection(IrEnumUnload);
|
|
MmUnlockPagableImageSection(PagedCodeSectionHandle);
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
VOID
|
|
IrEnumUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
{
|
|
|
|
D_PNP(DbgPrint("IRENUM: UnLoad\n");)
|
|
|
|
FREE_POOL(DriverEntryRegPath.Buffer);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
UnHandledDispatch(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS Status=STATUS_NOT_SUPPORTED;
|
|
PFDO_DEVICE_EXTENSION DeviceExtension=DeviceObject->DeviceExtension;
|
|
|
|
if (DeviceExtension->DoType == DO_TYPE_FDO) {
|
|
//
|
|
// this irp is for the parent devnode, just send it down the stack
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
Status=IoCallDriver(DeviceExtension->LowerDevice, Irp);
|
|
|
|
} else {
|
|
//
|
|
// this irp is for the child PDO, it does not handle this irp
|
|
// since it is at the bottom of the stack by definition, it can only complete it
|
|
//
|
|
#if DBG
|
|
PIO_STACK_LOCATION IrpSp=IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
D_ERROR(DbgPrint("IRENUM: Unhandled irp for PDO: mj= %x\n",IrpSp->MajorFunction);)
|
|
#endif
|
|
|
|
Irp->IoStatus.Status=Status;
|
|
Irp->IoStatus.Information=0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
return Status;
|
|
}
|