NT4/private/ntos/io/pnpdd.c
2020-09-30 17:12:29 +02:00

361 lines
9.6 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
All rights reserved
Module Name:
pnpdd.c
Abstract:
This module implements new Plug-And-Play driver entries and IRPs.
Author:
Shie-Lin Tzong (shielint) June-16-1995
Environment:
Kernel mode only.
Revision History:
*/
#include "iop.h"
#if _PNP_POWER_
typedef struct _DEVICE_CHANGE_COMPLETION_CONTEXT {
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
} DEVICE_CHANGE_COMPLETION_CONTEXT, *PDEVICE_CHANGE_COMPLETION_CONTEXT;
NTSTATUS
IopReconfigureResources(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN DRIVER_RECONFIGURE_OPERATION Operation,
IN PCM_RESOURCE_LIST CmResources
);
NTSTATUS
IoAddDevice (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING ServiceKeyName,
IN OUT PULONG InstanceNumber
);
NTSTATUS
IoRemoveDevice (
IN PDEVICE_OBJECT TargetDevice,
IN ULONG IrpMinorCode
);
NTSTATUS
IopDeviceRemovalComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, IopReconfigureResources)
#pragma alloc_text(PAGE, IoAddDevice)
#pragma alloc_text(PAGE, IoRemoveDevice)
#endif
NTSTATUS
IopReconfigureResources(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN DRIVER_RECONFIGURE_OPERATION Operation,
IN PCM_RESOURCE_LIST CmResources
)
/*++
Routine Description:
This function sends Reconfiguration related requests to device drivers.
Arguments:
DriverObject - Supplies the driver object of the device driver being queried
or reconfigured.
DeviceObject - Supplies the device object of the device being queried or
reconfigured. If the resources being reconfigured are driver specific,
this parameter will be NULL.
Operation - Specifies the operation requested.
ResourceList - Supplies the new resource list for the device/driver.
This parameter is specified only if Operation is either
QueryReconfigureResources or ReconfigureResources.
Return Value:
NTSTATUS code.
--*/
{
PDRIVER_RECONFIGURE_DEVICE reconfigRoutine;
NTSTATUS status = STATUS_NOT_IMPLEMENTED;
PAGED_CODE();
reconfigRoutine = DriverObject->DriverExtension->ReconfigureDevice;
if (reconfigRoutine != NULL) {
status = (reconfigRoutine) ( DriverObject,
DeviceObject,
Operation,
CmResources
);
}
return status;
}
NTSTATUS
IoAddDevice (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING ServiceKeyName,
IN OUT PULONG InstanceNumber
)
/*++
Routine Description:
This functions is used by Pnp manager to inform device driver to add a device to
its device list or is used by Pnp enumerator to give device driver a chance to
report/detect devices at run time.
If run time device detection is desired, the AddDevice entry will be invoked with
InstanceNumber = PLUG_PLAY_NO_INSTANCE. (For example, bus extender drivers will
use this interface to report new bus detected at run time.) If the driver
responses the call with a new device instance, it will be called repeatedly until
a STATUS_NO_MORE_ENTRIES is returned. For a driver which does not support run time
detection, it can simply return STATUS_NO_MORE_ENTRIES when its AddDevice entry is
invoked with InstanceNumber = PLUG_PLAY_NO_INSTANCE.
Parameters:
DriverObject - Supplies a driver object to receive the add device request.
ServiceKeyName - Supplies the name of the subkey in the system service list
(HKEY_LOCAL_MACHINE\CurrentControlSet\Services) that caused the driver to load.
InstanceNumber - Supplies an ordinal value indicating the device instance to be
added or PLUG_PLAY_NO_INSTANCE to initiate device/bus run time detection.
Return Value:
NTSTATUS code.
--*/
{
PDRIVER_ADD_DEVICE addDeviceRoutine;
NTSTATUS status = STATUS_NOT_IMPLEMENTED;
PAGED_CODE();
addDeviceRoutine = DriverObject->DriverExtension->AddDevice;
if (addDeviceRoutine != NULL) {
status = (addDeviceRoutine) ( ServiceKeyName, InstanceNumber );
}
return status;
}
NTSTATUS
IoRemoveDevice (
IN PDEVICE_OBJECT TargetDevice,
IN ULONG IrpMinorCode
)
/*++
Routine Description:
This function sends a requested DeviceRemoval irp to the top level device
object which roots on TargetDevice. If there is a VPB associated with the
TargetDevice, the corresponding filesystem's VDO will be used. Otherwise
the irp will be sent directly to the target device/ or its assocated device
object.
Parameters:
TargetDevice - Supplies the device object of the device being removed.
Operation - Specifies the operation requested.
The following IRP codes are used with IRP_MJ_DEVICE_CHANGE for removing
devices:
IRP_MN_QUERY_REMOVE_DEVICE
IRP_MN_CANCEL_REMOVE_DEVICE
IRP_MN_REMOVE_DEVICE
Return Value:
NTSTATUS code.
--*/
{
PDEVICE_OBJECT deviceObject;
PDEVOBJ_EXTENSION deviceExtension;
PIRP irp;
PIO_STACK_LOCATION irpSp;
DEVICE_CHANGE_COMPLETION_CONTEXT completionContext;
NTSTATUS status;
PAGED_CODE();
ASSERT(IrpMinorCode == IRP_MN_QUERY_REMOVE_DEVICE ||
IrpMinorCode == IRP_MN_CANCEL_REMOVE_DEVICE ||
IrpMinorCode == IRP_MN_REMOVE_DEVICE);
//
// If the target device object has a VPB associated with it.
// make the filesystem's volume device object the irp target.
//
if (TargetDevice->Vpb) {
deviceObject = TargetDevice->Vpb->DeviceObject;
} else {
deviceObject = TargetDevice;
}
//
// Get a pointer to the topmost device object in the stack of devices,
// beginning with the deviceObject.
//
deviceObject = IoGetAttachedDevice(deviceObject);
deviceExtension = deviceObject->DeviceObjectExtension;
//
// Allocate an I/O Request Packet (IRP) for this device removal operation.
//
irp = IoAllocateIrp( (CCHAR) (deviceObject->StackSize + 1), FALSE );
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Copy some state into the first stack location
//
irpSp = IoGetNextIrpStackLocation (irp);
irpSp->Parameters.Others.Argument1 = (PVOID) TargetDevice;
irpSp->Parameters.Others.Argument2 = (PVOID) IrpMinorCode;
//
// Get a pointer to the next stack location in the packet. This location
// will be used to pass the function codes and parameters to the first
// driver.
//
IoSetNextIrpStackLocation (irp);
irpSp = IoGetNextIrpStackLocation (irp);
//
// Fill in the IRP according to this request.
//
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->RequestorMode = KernelMode;
irp->UserIosb = NULL;
irp->UserEvent = NULL;
irpSp->MajorFunction = IRP_MJ_DEVICE_CHANGE;
irpSp->MinorFunction = (UCHAR)IrpMinorCode;
irpSp->Parameters.RemoveDevice.DeviceToRemove = TargetDevice;
KeInitializeEvent( &completionContext.Event, SynchronizationEvent, FALSE );
IoSetCompletionRoutine(irp,
IopDeviceRemovalComplete,
&completionContext, /* Completion context */
TRUE, /* Invoke on success */
TRUE, /* Invoke on error */
TRUE /* Invoke on cancel */
);
//
// Hold the device object's Device Queue and Send the request packet to the
// appropriate driver...
//
IoHoldDeviceQueue(deviceObject, irp);
status = IoCallDriver( deviceObject, irp );
if (status == STATUS_PENDING) {
(VOID) KeWaitForSingleObject( &completionContext.Event,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER) NULL );
}
return completionContext.IoStatus.Status;
}
NTSTATUS
IopDeviceRemovalComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
Completion function for a DeviceRemoval IRP. The device objects'
StartIoHoldingQueue will be released if no other queue holding irp
pending.
Arguments:
DeviceObject - NULL.
Irp - SetPower irp which has completed
Context - a pointer to the DEVICE_CHANGE_COMPLETION_CONTEXT.
Return Value:
STATUS_MORE_PROCESSING_REQUIRED is returned to IoCompleteRequest
to signify that IoCompleteRequest should not continue processing
the IRP.
--*/
{
PIO_STACK_LOCATION irpSp;
PDEVOBJ_EXTENSION deviceObjectExt;
PDEVICE_OBJECT deviceObject;
ULONG irpCode;
//
// Read state from Irp.
//
irpSp = IoGetCurrentIrpStackLocation (Irp);
deviceObject = irpSp->DeviceObject;
irpCode = (ULONG)irpSp->Parameters.Others.Argument2;
if ((irpCode == IRP_MN_QUERY_REMOVE_DEVICE && !NT_SUCCESS (Irp->IoStatus.Status)) ||
irpCode != IRP_MN_REMOVE_DEVICE) {
//
// Release any irps which were postponded from IoStartPacket if
// it is NOT a device removal irp and if a driver returned failure to query.
//
IoReleaseStartIoHoldingQueue(deviceObject);
}
//
// Irp processing is complete, free the irp and then return
// more_processing_requered which causes IoCompleteRequest to
// stop "completing" this irp any future.
//
IoFreeIrp (Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
#endif // _PNP_POWER_