390 lines
8.5 KiB
C
390 lines
8.5 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"
|
|
|
|
|
|
#pragma alloc_text(PAGE,IrEnumAddDevice)
|
|
#pragma alloc_text(PAGE,IrEnumPnP)
|
|
#pragma alloc_text(PAGE,IrEnumPower)
|
|
#pragma alloc_text(PAGE,IrEnumWmi)
|
|
|
|
NTSTATUS
|
|
IrEnumAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo
|
|
)
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PDEVICE_OBJECT Fdo = NULL;
|
|
|
|
PDEVICE_OBJECT LowerDevice=NULL;
|
|
|
|
//
|
|
// Pointer to the device extension created for this
|
|
// device
|
|
//
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = NULL;
|
|
|
|
D_PNP(DbgPrint("IRENUM: AddDevice\n");)
|
|
|
|
//
|
|
// Create the device object for this device.
|
|
//
|
|
|
|
Status = IoCreateDevice(
|
|
DriverObject,
|
|
sizeof(FDO_DEVICE_EXTENSION),
|
|
NULL,
|
|
FILE_DEVICE_NULL,
|
|
FILE_AUTOGENERATED_DEVICE_NAME,
|
|
FALSE,
|
|
&Fdo
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
goto CleanUp;
|
|
}
|
|
|
|
LowerDevice=IoAttachDeviceToDeviceStack(
|
|
Fdo,
|
|
Pdo
|
|
);
|
|
|
|
if (LowerDevice == NULL) {
|
|
|
|
D_ERROR(DbgPrint("IRENUM: Could not attach to PDO\n");)
|
|
|
|
Status=STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto CleanUp;
|
|
}
|
|
|
|
Fdo->Flags |= LowerDevice->Flags;
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
Fdo->StackSize=LowerDevice->StackSize+1;
|
|
|
|
DeviceExtension=Fdo->DeviceExtension;
|
|
|
|
DeviceExtension->DoType=DO_TYPE_FDO;
|
|
|
|
DeviceExtension->DeviceObject = Fdo;
|
|
DeviceExtension->Pdo=Pdo;
|
|
DeviceExtension->LowerDevice=LowerDevice;
|
|
|
|
DeviceExtension->CreateStaticDevice= (EnumStaticDevice != 0) ;
|
|
|
|
CreateEnumObject(Fdo,&DeviceExtension->EnumHandle,DeviceExtension->CreateStaticDevice);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
CleanUp:
|
|
|
|
IoDeleteDevice(Fdo);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrEnumPnP(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
|
|
|
|
if ((DeviceExtension->DoType==DO_TYPE_PDO) || (DeviceExtension->DoType==DO_TYPE_DEL_PDO)) {
|
|
//
|
|
// this one is for the child
|
|
//
|
|
return IrEnumPdoPnp(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
}
|
|
|
|
if (DeviceExtension->DoType != DO_TYPE_FDO) {
|
|
|
|
DbgPrint("IRENUM: IrEnumPnp: Bad DevObj\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
IoCompleteRequest(
|
|
Irp,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_QUERY_STOP_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_CANCEL_STOP_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_STOP_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS: {
|
|
|
|
PDEVICE_RELATIONS CurrentRelations=(PDEVICE_RELATIONS)Irp->IoStatus.Information;
|
|
PDEVICE_RELATIONS NewRelations=NULL;
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_QUERY_DEVICE_RELATIONS type=%d\n",irpSp->Parameters.QueryDeviceRelations.Type);)
|
|
D_PNP(DbgPrint(" Information=%p\n",Irp->IoStatus.Information);)
|
|
|
|
|
|
switch (irpSp->Parameters.QueryDeviceRelations.Type ) {
|
|
|
|
case BusRelations: {
|
|
|
|
if (DeviceExtension->EnumHandle != NULL) {
|
|
|
|
status=GetDeviceList(
|
|
DeviceExtension->EnumHandle,
|
|
Irp
|
|
);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
IoCompleteRequest(
|
|
Irp,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
return status;
|
|
}
|
|
|
|
}
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
}
|
|
|
|
case TargetDeviceRelation:
|
|
default: {
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_QUERY_REMOVE_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_CANCEL_REMOVE_DEVICE\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL: {
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_SURPRISE_REMOVAL\n");)
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IRP_MN_REMOVE_DEVICE: {
|
|
|
|
ULONG NewReferenceCount;
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_REMOVE_DEVICE\n");)
|
|
//
|
|
// removing now for sure
|
|
//
|
|
DeviceExtension->Removing=TRUE;
|
|
DeviceExtension->Removed=TRUE;
|
|
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
status=IoCallDriver(DeviceExtension->LowerDevice, Irp);
|
|
|
|
//
|
|
// detach from the driver below
|
|
//
|
|
IoDetachDevice(DeviceExtension->LowerDevice);
|
|
|
|
DeviceExtension->DoType=DO_TYPE_DEL_FDO;
|
|
|
|
if (DeviceExtension->EnumHandle != NULL) {
|
|
|
|
CloseEnumObject(DeviceExtension->EnumHandle);
|
|
}
|
|
|
|
//
|
|
// delete our device object
|
|
//
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
D_PNP(DbgPrint("IRENUM: IRP_MN_REMOVE_DEVICE exit, %08lx\n",status);)
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
D_PNP(DbgPrint("IRENUM: Sending to PDO PnP IRP, MN func=%d\n",irpSp->MinorFunction);)
|
|
|
|
return ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
}
|
|
|
|
|
|
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrEnumPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
if ((DeviceExtension->DoType==DO_TYPE_PDO) || (DeviceExtension->DoType==DO_TYPE_DEL_PDO)) {
|
|
//
|
|
// this one is for the child
|
|
//
|
|
return IrEnumPdoPower(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
}
|
|
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return PoCallDriver(DeviceExtension->LowerDevice, Irp);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
IrEnumWmi(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
PFDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION irpSp=IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS Status;
|
|
|
|
if ((DeviceExtension->DoType==DO_TYPE_PDO) || (DeviceExtension->DoType==DO_TYPE_DEL_PDO)) {
|
|
|
|
return IrEnumPdoWmi(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
}
|
|
|
|
if (irpSp->Parameters.WMI.ProviderId == (ULONG_PTR)DeviceObject) {
|
|
//
|
|
// The irp was targeted at this device, but we don't support wmi
|
|
//
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
} else {
|
|
//
|
|
// the irp is targeted at another device object in the stack
|
|
//
|
|
Status=ForwardIrp(DeviceExtension->LowerDevice, Irp);
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|